@material-ui/core#ListItemAvatar TypeScript Examples

The following examples show how to use @material-ui/core#ListItemAvatar. 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: ReviewListItem.tsx    From ra-enterprise-demo with MIT License 6 votes vote down vote up
ReviewListItem: FC<any> = props => {
    const { data, onClick } = props;
    const classes = useStyles();
    const { content } = data;

    if (!content) {
        return null;
    }

    return (
        <ListItem
            button
            component={SearchListItemLink}
            data={data}
            onClick={onClick}
            alignItems="flex-start"
        >
            <ListItemAvatar className={classes.avatar}>
                <Avatar alt={content.reference}>
                    <CommentIcon fontSize="large" />
                </Avatar>
            </ListItemAvatar>
            <ListItemText
                primary={<Rating value={content.rating} readOnly />}
                secondary={<ReviewComment comment={content.comment} />}
                // @ts-ignore Could not make TS happy
                secondaryTypographyProps={secondaryTypographyProps}
            />
        </ListItem>
    );
}
Example #2
Source File: PlayersContainer.tsx    From cards-against-formality-pwa with BSD 2-Clause "Simplified" License 6 votes vote down vote up
Player = ({ player, isHost, isCzar, onPlayerKick, isCurrentUserHost }: any) => {
  function renderIcon() {
    return <div style={!isCzar ? { opacity: 0 } : {}}>
      <ListItemAvatar>
        <Avatar>
          <StyleIcon />
        </Avatar>
      </ListItemAvatar>
    </div>
  }

  function renderKick() {
    if (isHost || !isCurrentUserHost) {
      return null;
    }

    return <ListItemSecondaryAction style={{ right: '-10px' }}>
      <Button color="secondary" onClick={() => { onPlayerKick(player?._id) }}>Kick</Button>
    </ListItemSecondaryAction>
  }

  return <ListItem>
    {renderIcon()}
    <ListItemText primary={player.username} secondary={`Score: ${!player?.score ? 0 : player.score}`} />
    {renderKick()}
  </ListItem>;
}
Example #3
Source File: ConnectWallet.tsx    From homebase-app with MIT License 6 votes vote down vote up
ConnectWallet: React.FC = () => {
  const { connect } = useTezos();

  return (
    <PageContainer container justify="flex-start" alignItems="center">
      <Grid item>
        <SpacingTitle align="left" variant="h3" color="textSecondary">
          Connect your wallet
        </SpacingTitle>
        <SpacingTitle align="left" variant="subtitle1" color="textSecondary">
          Create an organization by picking a template below
        </SpacingTitle>
        <Box>
          <List>
            <ListItem button={true} onClick={() => connect()}>
              <ListItemAvatar>
                <Avatar>
                  <ImageIcon />
                </Avatar>
              </ListItemAvatar>
              <ListItemText>
                <Typography variant="subtitle1" color="textSecondary">
                  {" "}
                  Connect
                </Typography>{" "}
              </ListItemText>
            </ListItem>
          </List>
        </Box>
      </Grid>
    </PageContainer>
  );
}
Example #4
Source File: LiveStreamListItem.tsx    From twitch-live-extension with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
LiveStreamListItem = (elem: FollowedLivestream) => {
    const classes = useStyles();
    const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null);
    const handlePopoverOpen = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
        setAnchorEl(event.currentTarget);
    };
    const [elapsedTime, setElapsedTime] = useState(getElapsedTime(elem.started_at));

    useEffect(() => {
        const timer = setInterval(() => {
            setElapsedTime(getElapsedTime(elem.started_at));
        }, 1000);

        return () => clearInterval(timer);
    }, [elem.started_at]);

    const handlePopoverClose = () => {
        setAnchorEl(null);
    };

    const open = Boolean(anchorEl);

    return (
        <>
            <ListItem
                className={classes.root}
                button
                component="a"
                target="_blank"
                rel="noopener noreferrer"
                href={elem.url}
                divider
                dense
                onMouseEnter={handlePopoverOpen}
                onMouseLeave={handlePopoverClose}
            >
                <ListItemAvatar>
                    <Avatar src={elem.profile_image_url} />
                </ListItemAvatar>
                <ListItemText
                    className={classes.streamerDiv}
                    primary={elem.display_name}
                    secondary={
                        <Typography
                            className={classes.gameText}
                            noWrap
                            variant={'subtitle2'}
                            color={'textSecondary'}
                        >
                            {elem.game}
                        </Typography>
                    }
                />
                <ListItemSecondaryAction>
                    <IconButton edge="end" disabled size={'small'}>
                        <Typography
                            noWrap
                            variant={'subtitle1'}
                            color={'textSecondary'}
                            className={classes.viewersText}
                        >
                            {formatViewers(elem.viewer_count)}
                        </Typography>
                        <ViewerIcon />
                    </IconButton>
                    <Typography
                        noWrap
                        variant={'subtitle2'}
                        color={'textSecondary'}
                        className={classes.elapsedTimeText}
                    >
                        {elapsedTime}
                    </Typography>
                </ListItemSecondaryAction>
            </ListItem>
            <PopperTitle title={elem.title} anchorEl={anchorEl} open={open} />
        </>
    );
}
Example #5
Source File: AddServerDialog.tsx    From shadowsocks-electron with GNU General Public License v3.0 5 votes vote down vote up
AddServerDialog: React.FC<AddServerDialog> = props => {
  const { onClose, open } = props;
  const { t } = useTranslation();

  return (
    <AdaptiveDialog onClose={() => onClose('')} open={open}>
      <DialogTitle attr='' onClose={onClose}>{t('add_server')}</DialogTitle>
      <List>
        <ListItemButton button onClick={() => onClose("manual")}>
          <ListItemAvatar>
            <CreateIcon />
          </ListItemAvatar>
          <ListItemText primary={t('add_server_manually')} />
        </ListItemButton>
        <ListItemButton button onClick={() => onClose("qrcode")}>
          <ListItemAvatar>
            <CameraIcon />
          </ListItemAvatar>
          <ListItemText primary={t('scan_qt_code_from_screen')} />
        </ListItemButton>
        <ListItemButton button onClick={() => onClose("url")}>
          <ListItemAvatar>
            <CopyIcon />
          </ListItemAvatar>
          <ListItemText primary={
            <TextWithTooltip
              text={t('import_server_url_from_clipboard')}
              tooltip={t('import_server_url_from_clipboard_tips')}
            />
          } />
        </ListItemButton>
        <ListItemButton button onClick={() => onClose("subscription")}>
          <ListItemAvatar>
            <CopyIcon />
          </ListItemAvatar>
          <ListItemText primary={
            <TextWithTooltip
              text={t('import_server_subscription_from_clipboard')}
              tooltip={t('import_server_subscription_from_clipboard_tips')}
            />
          }
          />
        </ListItemButton>
      </List>
    </AdaptiveDialog>
  );
}
Example #6
Source File: ProductListItem.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
ProductListItem: FC<any> = props => {
    const { data, onClick } = props;
    const { content } = data;

    const classes = useProductListItemStyles();
    const translate = useTranslate();

    if (!content) {
        return null;
    }

    return (
        <ListItem
            button
            component={SearchListItemLink}
            data={data}
            onClick={onClick}
            alignItems="flex-start"
            className={classes.root}
        >
            <ListItemAvatar className={classes.avatar}>
                <div className={classes.art}>
                    <img src={content.thumbnail} alt={content.reference} />
                </div>
            </ListItemAvatar>
            <ListItemText
                primary={
                    <Typography color="textPrimary">
                        {content.reference}
                    </Typography>
                }
                secondary={
                    content.reviews > 0 ? (
                        <Box
                            component="ul"
                            display="flex"
                            justifyContent="space-between"
                            padding={0}
                            marginTop={1}
                            marginBottom={1}
                        >
                            <LinkedData
                                icon={<CommentIcon />}
                                label={translate('resources.reviews.name', {
                                    smart_count: 2,
                                })}
                                to={`/reviews?filter=%7B"product_id"%3A${content.id}%7D`}
                            >
                                {content.reviews}
                            </LinkedData>
                        </Box>
                    ) : undefined
                }
                // @ts-ignore Could not make TS happy
                secondaryTypographyProps={secondaryTypographyProps}
            />
        </ListItem>
    );
}
Example #7
Source File: CommandListItem.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
CommandListItem: FC<any> = props => {
    const { data, onClick } = props;
    const { content } = data;

    const classes = useCommandListItemStyles();
    const translate = useTranslate();

    if (!content) {
        return null;
    }

    return (
        <ListItem
            button
            component={SearchListItemLink}
            data={data}
            onClick={onClick}
            alignItems="flex-start"
        >
            <ListItemAvatar className={classes.avatar}>
                <Avatar alt={content.reference}>
                    <ShoppingCartIcon fontSize="large" />
                </Avatar>
            </ListItemAvatar>
            <Grid className={classes.root} container spacing={2}>
                <Grid container item xs>
                    <Grid item xs={8}>
                        <Typography
                            variant="body1"
                            color="textPrimary"
                            gutterBottom
                        >
                            Ref. {content.reference}
                        </Typography>
                    </Grid>
                    <Grid item xs={4}>
                        <CommandStatus status={content.status} />
                    </Grid>
                    <Grid item xs={12}>
                        <Typography
                            variant="body2"
                            color="textPrimary"
                            gutterBottom
                        >
                            {new Date(content.date).toLocaleDateString()}
                            &nbsp;-&nbsp;
                            {`${content.customer.first_name} ${content.customer.last_name}`}
                            &nbsp;-&nbsp;
                            {`${translate(
                                'resources.commands.fields.basket.total'
                            )} ${content.total}`}
                            €
                        </Typography>
                    </Grid>
                </Grid>
            </Grid>
        </ListItem>
    );
}
Example #8
Source File: PendingReviews.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
PendingReviews = ({
    reviews = [],
    customers = {},
}: {
    reviews?: Review[];
    customers?: { [key: string]: Customer };
}): React.ReactElement => {
    const classes = useStyles();
    const translate = useTranslate();
    return (
        <Card className={classes.root}>
            <CardHeader title={translate('pos.dashboard.pending_reviews')} />
            <List>
                {reviews.map((record: Review) => (
                    <ListItem
                        key={record.id}
                        button
                        component={Link}
                        to={`/reviews/${record.id}`}
                        alignItems="flex-start"
                    >
                        <ListItemAvatar>
                            {customers[record.customer_id] ? (
                                <Avatar
                                    src={`${
                                        customers[record.customer_id].avatar
                                    }?size=32x32`}
                                    className={classes.avatar}
                                />
                            ) : (
                                <Avatar />
                            )}
                        </ListItemAvatar>

                        <ListItemText
                            primary={<StarRatingField record={record} />}
                            secondary={record.comment}
                            className={classes.listItemText}
                            style={{ paddingRight: 0 }}
                        />
                    </ListItem>
                ))}
            </List>
        </Card>
    );
}
Example #9
Source File: NewCustomers.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
NewCustomers = (): ReactElement => {
    const translate = useTranslate();
    const classes = useStyles();
    const aMonthAgo = useMemo(() => {
        const date = new Date();
        date.setDate(date.getDate() - 30);
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date;
    }, []);

    const { loaded, data: visitors } = useQueryWithStore({
        type: 'getList',
        resource: 'customers',
        payload: {
            filter: {
                has_ordered: true,
                first_seen_gte: aMonthAgo.toISOString(),
            },
            sort: { field: 'first_seen', order: 'DESC' },
            pagination: { page: 1, perPage: 100 },
        },
    });

    if (!loaded) {
        return <Loading />;
    }
    return (
        <Card className={classes.root}>
            <CardHeader title={translate('pos.dashboard.new_customers')} />
            <List>
                {visitors
                    ? visitors.map((record: Customer) => (
                          <ListItem
                              button
                              to={`/customers/${record.id}`}
                              component={Link}
                              key={record.id}
                          >
                              <ListItemAvatar>
                                  <Avatar src={`${record.avatar}?size=32x32`} />
                              </ListItemAvatar>
                              <ListItemText
                                  primary={`${record.first_name} ${record.last_name}`}
                              />
                          </ListItem>
                      ))
                    : null}
            </List>
        </Card>
    );
}
Example #10
Source File: UploadWarnings.tsx    From aqualink-app with MIT License 5 votes vote down vote up
DetailsDialog = ({ open, details, onClose }: DetailsDialogProps) => {
  const classes = useStyles();

  return (
    <Dialog maxWidth="md" fullWidth open={open} onClose={onClose}>
      <DialogTitle disableTypography className={classes.dialogTitle}>
        <Typography variant="h4">Upload Details</Typography>
        <IconButton className={classes.closeButton} onClick={onClose}>
          <CloseIcon />
        </IconButton>
      </DialogTitle>
      <DialogContent>
        <List>
          {details.map(({ file, ignoredHeaders }, index) =>
            ignoredHeaders?.length ? (
              // eslint-disable-next-line react/no-array-index-key
              <ListItem key={`${file}-${index}`}>
                <ListItemAvatar>
                  <Avatar className={classes.avatar}>
                    <WarningIcon />
                  </Avatar>
                </ListItemAvatar>
                <ListItemText
                  primary={file}
                  primaryTypographyProps={{
                    color: "textSecondary",
                    variant: "h5",
                  }}
                  secondary={`
                      These columns are not configured for import yet and were
                      not uploaded: ${ignoredHeaders
                        .map((header) => `"${header}"`)
                        .join(", ")}.
                    `}
                  secondaryTypographyProps={{ variant: "subtitle1" }}
                />
              </ListItem>
            ) : null
          )}
        </List>
      </DialogContent>
    </Dialog>
  );
}
Example #11
Source File: index.tsx    From Demae with MIT License 5 votes vote down vote up
OrderList = () => {
	const theme = useTheme()
	const [user, isLoading] = useUser()
	const ref = user?.orders.collectionReference
	const [orders, isDataLoading] = useDataSourceListen<Order>(Order, {
		path: ref?.path,
		orderBy: OrderBy("createdAt", "desc"),
		limit: 100
	}, isLoading)

	if (isDataLoading) {
		return (
			<Paper>
				<DataLoading />
			</Paper>
		)
	}

	if (orders.length === 0) {
		return <Box padding={3} display="flex" justifyContent="center" fontWeight={600} fontSize={20}>There are no orders.</Box>
	}

	return (
		<Paper>
			<List style={{
				height: "100%"
			}}>
				{orders.map(data => {
					const orderedDate = Dayjs(data.createdAt.toDate())
					return (
						<ListItem key={data.id} button alignItems="flex-start" component={Link} to={`/account/orders/${data.id}`}>
							<ListItemAvatar>
								<Avatar variant="rounded" src={data.imageURLs()[0]} style={{
									height: theme.spacing(5),
									width: theme.spacing(5)
								}}>
									<ImageIcon />
								</Avatar>
							</ListItemAvatar>
							<ListItemText primary={
								<>
									<Typography variant="subtitle1">
										{data.title}
									</Typography>
									<Typography variant="body2">
										{`ID: ${data.id}`}
									</Typography>
									<Typography variant="caption">
										{orderedDate.format("YYYY-MM-DD HH:mm:ss")}
									</Typography>
									<Box display="flex" paddingY={1}>
										{data.salesMethod === "online" && <Label color="gray" fontSize={12}>{DeliveryStatusLabel[data.deliveryStatus]}</Label>}
										<Label color="gray" fontSize={12}>{PaymentStatusLabel[data.paymentStatus]}</Label>
									</Box>
								</>
							} />
						</ListItem>
					)
				})}
			</List>
		</Paper>
	)
}
Example #12
Source File: UserListItem.tsx    From End-to-End-Web-Testing-with-Cypress with MIT License 5 votes vote down vote up
UserListItem: React.FC<UserListItemProps> = ({ user, setReceiver, index }) => {
  return (
    <ListItem data-test={`user-list-item-${user.id}`} onClick={() => setReceiver(user)}>
      <ListItemAvatar>
        <Avatar src={user.avatar} />
      </ListItemAvatar>
      <ListItemText
        primary={`${user.firstName} ${user.lastName}`}
        secondary={
          <span>
            <Grid
              component={"span"}
              container
              direction="row"
              justify="flex-start"
              alignItems="flex-start"
              spacing={1}
            >
              <Grid item component={"span"}>
                <b>U: </b>
                {user.username}
              </Grid>
              <Grid item component={"span"}>
                &bull;
              </Grid>
              <Grid item component={"span"}>
                <b>E: </b>
                {user.email}
              </Grid>
              <Grid item component={"span"}>
                &bull;
              </Grid>
              <Grid item component={"span"}>
                <b>P: </b>
                {user.phoneNumber}
              </Grid>
            </Grid>
          </span>
        }
      />
    </ListItem>
  );
}
Example #13
Source File: TransactionItem.tsx    From End-to-End-Web-Testing-with-Cypress with MIT License 5 votes vote down vote up
TransactionItem: React.FC<TransactionProps> = ({ transaction }) => {
  const classes = useStyles();
  const history = useHistory();

  const showTransactionDetail = (transactionId: string) => {
    history.push(`/transaction/${transactionId}`);
  };

  return (
    <ListItem
      data-test={`transaction-item-${transaction.id}`}
      alignItems="flex-start"
      onClick={() => showTransactionDetail(transaction.id)}
    >
      <Paper className={classes.paper} elevation={0}>
        <Grid container spacing={2}>
          <Grid item>
            <ListItemAvatar>
              <Badge
                overlap="circle"
                anchorOrigin={{
                  vertical: "bottom",
                  horizontal: "right",
                }}
                badgeContent={<SmallAvatar src={transaction.receiverAvatar} />}
              >
                <Avatar src={transaction.senderAvatar} />
              </Badge>
            </ListItemAvatar>
          </Grid>
          <Grid item xs={12} sm container>
            <Grid item xs container direction="column" spacing={2}>
              <Grid item xs>
                <TransactionTitle transaction={transaction} />
                <Typography variant="body2" color="textSecondary" gutterBottom>
                  {transaction.description}
                </Typography>
                <Grid
                  container
                  direction="row"
                  justify="flex-start"
                  alignItems="flex-start"
                  spacing={1}
                  className={classes.socialStats}
                >
                  <Grid item>
                    <LikeIcon className={classes.countIcons} />
                  </Grid>
                  <Grid item>
                    <Typography data-test="transaction-like-count" className={classes.countText}>
                      {transaction.likes.length}
                    </Typography>
                  </Grid>
                  <Grid item>
                    <CommentIcon className={classes.countIcons} />
                  </Grid>
                  <Grid item>
                    <Typography data-test="transaction-comment-count" className={classes.countText}>
                      {transaction.comments.length}
                    </Typography>
                  </Grid>
                </Grid>
              </Grid>
            </Grid>
            <Grid item>
              <TransactionAmount transaction={transaction} />
            </Grid>
          </Grid>
        </Grid>
      </Paper>
    </ListItem>
  );
}
Example #14
Source File: index.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
Notification = () => {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(
    null
  );

  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const id = open ? "simple-popover" : undefined;

  const notifications: Notification[] = [
    {
      title: "a",
      subtitle: "a",
      variant: "error",
      link:
        "https://console.cloud.google.com/cloud-build/builds;region=global/f7b8fd9b-eb6e-401f-a889-73c4bf75f232?project=antler-vc",
    },
  ];

  const notificationsCount = notifications.length;
  return (
    <>
      <IconButton onClick={handleClick}>
        <Badge
          color={"primary"}
          variant="standard"
          badgeContent={notificationsCount}
        >
          <BellIcon />
        </Badge>
      </IconButton>
      <Popover
        id={id}
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "center",
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "center",
        }}
      >
        <List>
          {notifications.map((notification) => (
            <ListItem>
              <ListItemAvatar>
                <Avatar>
                  <ErrorIcon />
                </Avatar>
              </ListItemAvatar>
              <ListItemText
                primary={notification.title}
                secondary={notification.subtitle}
              />
              <ListItemSecondaryAction>
                <IconButton edge="end" aria-label="delete">
                  <DeleteIcon />
                </IconButton>
              </ListItemSecondaryAction>
            </ListItem>
          ))}
        </List>
      </Popover>
    </>
  );
}
Example #15
Source File: comment.tsx    From jupyter-extensions with Apache License 2.0 4 votes vote down vote up
render() {
    const data = this.props.detachedComment
      ? this.props.detachedComment
      : this.props.reviewComment;

    return (
      <>
        <ListItem key="context">
          <CommentContext
            range={data.range}
            filePath={data.filePath}
            file={this.props.file}
          />
        </ListItem>
        <ListItem key="comment" alignItems="flex-start">
          <ListItemAvatar>
            <Avatar alt="avatar" />
          </ListItemAvatar>
          <ListItemText
            primary={
              <div>
                <p style={style.username}> {data.author} </p>
                <p style={style.date}> {data.timestamp} </p>
              </div>
            }
            secondary={
              <Typography
                variant="body2"
                style={style.inline}
                color="textPrimary"
              >
                {data.text}
              </Typography>
            }
          />
        </ListItem>
        <div style={style.commentBottom}>
          <Button
            color="primary"
            size="small"
            onClick={() => {
              this.setState({
                showCommentEditor: !this.state.showCommentEditor,
              });
            }}
            className="replyButton"
          >
            {' '}
            Reply{' '}
          </Button>
          {this.state.showCommentEditor &&
            (this.state.commentType === 'detached' ? (
              <NewReplyComment
                currFilePath={data.filePath}
                hash={data.hash}
                commentType={this.state.commentType}
              />
            ) : (
              <NewReplyComment
                currFilePath={data.filePath}
                hash={data.hash}
                commentType={this.state.commentType}
                reviewHash={this.props.reviewComment.request.reviewHash}
              />
            ))}
          {data.children && (
            <Button
              size="small"
              endIcon={
                this.state.expandThread ? (
                  <ArrowDropUpIcon />
                ) : (
                  <ArrowDropDownIcon />
                )
              }
              onClick={() => {
                this.setState({ expandThread: !this.state.expandThread });
              }}
              className="threadButton"
            >
              {' '}
              {this.state.expandThread ? 'Hide thread' : 'Show thread'}{' '}
            </Button>
          )}
        </div>
        <div style={style.threadIndent} className="threadList">
          {this.state.expandThread && data.children && (
            <List>
              {data.children.map((reply, index) => {
                if (this.props.detachedComment) {
                  const detached = createDetachedCommentFromJSON(
                    reply,
                    reply.filePath
                  );
                  return (
                    <Comment
                      detachedComment={detached}
                      file={this.props.file}
                      key={index}
                    />
                  );
                } else {
                  const review = createReviewCommentFromJSON(
                    reply,
                    this.props.reviewComment.revision,
                    this.props.reviewComment.request,
                    data.filePath
                  );
                  return (
                    <Comment
                      reviewComment={review}
                      file={this.props.file}
                      key={index}
                    />
                  );
                }
              })}
            </List>
          )}
        </div>
      </>
    );
  }
Example #16
Source File: KeyDisclosure.tsx    From DamnVulnerableCryptoApp with MIT License 4 votes vote down vote up
KeyDisclosure = (props: IChallengeProps) => {

  const classes = useStyles();
  const [inboxUnlocked, setInboxUnlocked] = useState(false);
  const [mailboxKey, setMailboxKey] = useState("");
  const [emails, setEmails] = useState<IEmail[]>([]);
  const [selectedEmail, setSelectedEmail] = useState<IEmail>({} as IEmail);
  const layoutContext = useContext(LayoutContext);


  useEffect(() => {
    props.setWarning("This challenge is intended for you to go to the source code of the application and search for something. "
      + "So don't waste your time, go to the project's github page and start digging");
  }, []);

  useEffect(() => {
    setEmailDetails();
  }, [selectedEmail]);

  const onChangeOpenEmail = (mail: IEmail) => {

    return (e: React.MouseEvent) => {
      setSelectedEmail(mail);
    };
  };

  const emailEntry = (index: number, mail: IEmail) => {
    const from = mail.from.split("<")[0];
    const img = mail.from.startsWith("Fake Reporter") ? FakeReporterImg : DetectiveImg;

    return (
      <List key={index}>
        <ListItem button onClick={onChangeOpenEmail(mail)}>
          <ListItemAvatar>
            <Avatar>
              <img src={img} width="50" />
            </Avatar>
          </ListItemAvatar>
          <ListItemText primary={from} secondary={mail.subject} />
        </ListItem>
      </List>
    );
  };


  const setEmailDetails = () => {
    if (!selectedEmail?.from) return;

    const img = selectedEmail.from.startsWith("Fake Reporter") ? FakeReporterImg : DetectiveImg;

    return (
      <Box p={2}>
        <Box display="flex">
          <Avatar><img src={img} width="50" /></Avatar>
          <Box ml={1}>
            <Typography><strong>Subject:</strong> {selectedEmail.subject}</Typography>
            <Typography><small><strong>Date: </strong>{selectedEmail.date}</small></Typography>
          </Box>
        </Box>


        <Box className={classes.emailBody}>
          <Typography>{selectedEmail.body} </Typography>
        </Box>
      </Box>
    );
  };


  return (
    <Box id="key-disclosure-container" style={{ position: 'relative' }}>


      <KeyModal inboxUnlocked={inboxUnlocked} mailboxKey={mailboxKey} setSelectedEmail={setSelectedEmail}
        setEmails={setEmails} setInboxUnlocked={setInboxUnlocked} setMailboxKey={setMailboxKey} setFlag={props.setFlag} />

      <Box mt={2}>
        <AppBar position="static" className={classes.tabs}>
          <Tabs value={0}>
            <Tab label="Inbox" icon={<DraftsIcon />} />
            <Tab label="Stared" icon={<StarIcon />} />
            <Tab label="Drafts" icon={<InsertDriveFileIcon />} />
          </Tabs>
        </AppBar>



        <div role="tabpanel">
          <Box>
            <Grid container className={classes.mailbox} >
              <Grid item sm={4} className={classes.emailList}>
                {
                  emails.map((mail, i) => emailEntry(i, mail))
                }
              </Grid>
              <Grid item sm={8} className={classes.emailDetails}>{setEmailDetails()}</Grid>
            </Grid>
          </Box>
        </div>
      </Box>

    </Box >
  );
}
Example #17
Source File: UserMenu.tsx    From firetable with Apache License 2.0 4 votes vote down vote up
export default function UserMenu(props: IconButtonProps) {
  const classes = useStyles();

  const anchorEl = useRef<HTMLButtonElement>(null);
  const [open, setOpen] = useState(false);
  const [themeSubMenu, setThemeSubMenu] = useState<EventTarget | null>(null);
  const [latestUpdate] = useLatestUpdateState<null | Record<string, any>>();

  const {
    currentUser,
    userDoc,
    theme,
    themeOverridden,
    setTheme,
    setThemeOverridden,
  } = useAppContext();
  if (!currentUser || !userDoc || !userDoc?.state?.doc)
    return <div className={classes.spacer} />;

  const displayName = userDoc?.state?.doc?.user?.displayName;
  const avatarUrl = userDoc?.state?.doc?.user?.photoURL;
  const email = userDoc?.state?.doc?.user?.email;

  const avatar = avatarUrl ? (
    <Avatar src={avatarUrl} className={classes.avatar} />
  ) : (
    <AccountCircleIcon color="secondary" />
  );

  const changeTheme = (option: "system" | "light" | "dark") => {
    switch (option) {
      case "system":
        setThemeOverridden(false);
        return;

      case "light":
        setTheme("light");
        break;

      case "dark":
        setTheme("dark");
        break;

      default:
        break;
    }
    setThemeOverridden(true);
  };

  return (
    <>
      <IconButton
        aria-label="Open user menu"
        aria-controls="user-menu"
        aria-haspopup="true"
        edge="end"
        {...props}
        ref={anchorEl}
        onClick={() => setOpen(true)}
        className={classes.iconButton}
      >
        {latestUpdate?.tag_name > "v" + meta.version ? (
          <Badge color="primary" overlap="circular" variant="dot">
            {avatar}
          </Badge>
        ) : (
          avatar
        )}
      </IconButton>

      <Menu
        anchorEl={anchorEl.current}
        id="user-menu"
        keepMounted
        anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
        getContentAnchorEl={null}
        transformOrigin={{ vertical: "top", horizontal: "right" }}
        open={open}
        onClose={() => setOpen(false)}
        classes={{ paper: classes.paper }}
      >
        <MenuItem
          component="a"
          href={`https://console.firebase.google.com/project/${projectId}/firestore/data/~2F_FT_USERS~2F${currentUser.uid}`}
          target="_blank"
          rel="noopener"
        >
          <ListItemAvatar>{avatar}</ListItemAvatar>
          <ListItemText primary={displayName} secondary={email} />
        </MenuItem>

        <Divider className={classes.divider} />

        <MenuItem onClick={(e) => setThemeSubMenu(e.target)}>
          Theme
          <ListItemSecondaryAction className={classes.secondaryAction}>
            <ArrowRightIcon className={classes.secondaryIcon} />
          </ListItemSecondaryAction>
        </MenuItem>

        {themeSubMenu && (
          <Menu
            anchorEl={themeSubMenu as any}
            id="theme-sub-menu"
            anchorOrigin={{ vertical: "top", horizontal: "left" }}
            getContentAnchorEl={null}
            transformOrigin={{ vertical: "top", horizontal: "right" }}
            open
            onClose={() => setThemeSubMenu(null)}
            classes={{ paper: classes.subMenu }}
          >
            <MenuItem onClick={() => changeTheme("system")}>
              <ListItemIcon>{!themeOverridden && <CheckIcon />}</ListItemIcon>
              System
            </MenuItem>
            <MenuItem onClick={() => changeTheme("light")}>
              <ListItemIcon>
                {themeOverridden && theme === "light" && <CheckIcon />}
              </ListItemIcon>
              Light
            </MenuItem>
            <MenuItem onClick={() => changeTheme("dark")}>
              <ListItemIcon>
                {themeOverridden && theme === "dark" && <CheckIcon />}
              </ListItemIcon>
              Dark
            </MenuItem>
          </Menu>
        )}

        <MenuItem component={Link} to={routes.signOut}>
          Sign out
        </MenuItem>

        <Divider className={classes.divider} />

        <UpdateChecker />
      </Menu>
    </>
  );
}
Example #18
Source File: CustomerListItem.tsx    From ra-enterprise-demo with MIT License 4 votes vote down vote up
CustomerListItem: FC<any> = props => {
    const { data, onClick } = props;
    const { content } = data;

    const classes = useStyles();
    const translate = useTranslate();

    if (!content) {
        return null;
    }

    const fullname = `${content.first_name} ${content.last_name}`;

    return (
        <ListItem
            button
            component={SearchListItemLink}
            data={data}
            onClick={onClick}
            alignItems="flex-start"
            className={classes.root}
            data-testid="customer"
        >
            <ListItemAvatar className={classes.avatar}>
                <Avatar alt={fullname} src={content.avatar} />
            </ListItemAvatar>
            <ListItemText
                primary={
                    <Typography color="textPrimary">{fullname}</Typography>
                }
                secondary={
                    <Box
                        component="ul"
                        display="flex"
                        justifyContent="flex-start"
                        padding={0}
                        marginTop={1}
                        marginBottom={1}
                    >
                        {content.pending_orders > 0 ? (
                            <LinkedData
                                icon={<ShoppingCartIcon />}
                                label={translate('resources.commands.name', {
                                    smart_count: 2,
                                })}
                                to={`/commands?filter=%7B"status"%3A"ordered"%2C"customer_id"%3A${content.id}%7D`}
                            >
                                {content.pending_orders}
                            </LinkedData>
                        ) : null}

                        {content.total_spent > 0 ? (
                            <LinkedData
                                icon={<DollarIcon />}
                                label={translate(
                                    'resources.customers.fields.total_spent'
                                )}
                                to={`/commands?filter=%7B"status"%3A"delivered"%2C"customer_id"%3A${content.id}%7D`}
                            >
                                {content.total_spent.toLocaleString()}
                            </LinkedData>
                        ) : null}
                        {content.reviews > 0 ? (
                            <LinkedData
                                icon={<CommentIcon />}
                                label={translate('resources.reviews.name', {
                                    smart_count: 2,
                                })}
                                to={`/reviews?filter=%7B"customer_id"%3A${content.id}%7D`}
                            >
                                {content.reviews}
                            </LinkedData>
                        ) : null}
                    </Box>
                }
                // @ts-ignore Could not make TS happy
                secondaryTypographyProps={secondaryTypographyProps}
            />
        </ListItem>
    );
}
Example #19
Source File: SKUList.tsx    From Demae with MIT License 4 votes vote down vote up
SKUListItem = ({ providerID, product, sku }: { providerID: string, product: Product, sku: SKU }) => {
	const classes = useStyles()
	const theme = useTheme()
	const [user] = useUser()
	const [cart] = useCart()
	const [showDialog] = useDialog()
	const [showModal, closeModal] = useModal()
	const mediatorID = useMediator()

	const imageURL = (sku.imagePaths().length > 0) ? sku.imagePaths()[0] : undefined
	const imgProps = useImage({ path: imageURL, alt: `${sku.name ?? ""} ${sku.caption ?? ""}`, sizes: "96px" })
	const amount = sku.price || 0
	const price = new Intl.NumberFormat("ja-JP", { style: "currency", currency: sku.currency }).format(amount)

	const withLogin = async (sku: SKU, onNext: (sku: SKU) => void) => {
		if (user) {
			onNext(sku)
		} else {
			showDialog("Please Login", undefined, [
				{
					title: "Cancel",
				},
				{
					title: "OK",
					variant: "contained",
					color: "primary",
					handler: () => {
						showModal(<Login onNext={async (user) => {
							onNext(sku)
							closeModal()
						}} />)
					}
				}
			])
		}
	}

	const addSKU = async (sku: SKU) => {
		withLogin(sku, async (sku) => {
			if (!product) return
			if (user) {
				const groupID = CartGroup.ID(product)
				if (cart) {
					const group = cart?.cartGroup(groupID) || CartGroup.fromSKU(product, sku)
					group.groupID = groupID
					group.addSKU(product, sku, mediatorID)
					cart?.setCartGroup(group)
					await cart.save()
				} else {
					const cart = new Cart(user.id)
					const group = cart?.cartGroup(groupID) || CartGroup.fromSKU(product, sku)
					group.groupID = groupID
					group.addSKU(product, sku, mediatorID)
					cart?.setCartGroup(group)
					await cart.save()
				}
			}
		})
	}

	const deleteSKU = async (sku: SKU) => {
		if (!cart) return
		const group = cart.cartGroup(providerID)
		group?.deleteSKU(sku)
		if ((group?.items.length || 0) <= 0) {
			cart.groups = cart.groups.filter(group => group.groupID !== providerID)
		}
		await cart.save()
	}

	return (
		<ListItem button component={Link} to={`/providers/${providerID}/products/${product.id}/skus/${sku.id}`}>
			<ListItemAvatar>
				<Avatar className={classes.avater} variant="rounded" {...imgProps}>
					<ImageIcon />
				</Avatar>
			</ListItemAvatar>
			<ListItemText
				primary={
					<>
						<Box mx={2} my={0} >
							<Box fontSize={16} fontWeight={800}>
								{sku.name}
							</Box>
							<Box>
								{price}
							</Box>
							<Box color="text.secondary">
								{sku.caption}
							</Box>
						</Box>
					</>
				}
				secondary={
					<>
						{/* <Box fontWeight="fontWeightMedium" fontSize="subtitle1" mx={2} my={0} >
								{`${ISO4217[product.currency]["symbol"]}${item.subtotal().toLocaleString()}`}
							</Box> */}
					</>
				} />
			<ListItemSecondaryAction>
				<Tooltip title="Delete" onClick={(e) => {
					e.stopPropagation()
					deleteSKU(sku)
				}}>
					<IconButton>
						<RemoveCircleIcon color="inherit" />
					</IconButton>
				</Tooltip>
				<Tooltip title="Add" onClick={(e) => {
					e.stopPropagation()
					addSKU(sku)
				}}>
					<IconButton>
						<AddCircleIcon color="inherit" />
					</IconButton>
				</Tooltip>
			</ListItemSecondaryAction>
		</ListItem>
	)
}
Example #20
Source File: global-search-field.tsx    From mtcute with GNU Lesser General Public License v3.0 4 votes vote down vote up
export function GlobalSearchField({ isMobile }: { isMobile: boolean }): React.ReactElement {
    const classes = useStyles()
    const allObjects: {
        allTlObject: GraphqlAllResponse<ExtendedTlObject>
    } = useStaticQuery(graphql`
        query {
            allTlObject {
                edges {
                    node {
                        id
                        prefix
                        type
                        name
                    }
                }
            }
        }
    `)

    const [includeMtproto, setIncludeMtproto] = useLocalState('mtproto', false)
    const { hits, query, onSearch } = useFuse(
        allObjects.allTlObject.edges,
        {
            keys: ['node.name'],
            includeMatches: true,
            threshold: 0.3,
        },
        { limit: 25 },
        includeMtproto ? undefined : (it) => it.node.prefix !== 'mtproto/'
    )

    const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null)
    const [open, setOpen] = useState(false)

    const notFound = () => (
        <>
            <ErrorOutlineIcon className={classes.popupEmptyIcon} />
            Nothing found
            {!includeMtproto && (
                <Button
                    variant="text"
                    size="small"
                    style={{
                        margin: '4px auto',
                    }}
                    onClick={() => {
                        setIncludeMtproto(true)
                    }}
                >
                    Retry including MTProto objects
                </Button>
            )}
        </>
    )

    const emptyField = () => (
        <>
            <SearchIcon className={classes.popupEmptyIcon} />
            Start typing...
        </>
    )

    const renderSearchItem = (
        node: ExtendedTlObject,
        matches: ReadonlyArray<Fuse.FuseResultMatch>
    ) => (
        <ListItem
            button
            divider
            component={Link}
            to={`/${node.prefix}${node.type}/${node.name}`}
            className={classes.popupListItem}
            onClick={() => setOpen(false)}
            key={node.id}
        >
            <ListItemAvatar>
                <Avatar
                    style={{
                        backgroundColor:
                            node.type === 'class'
                                ? blue[600]
                                : node.type === 'method'
                                ? red[600]
                                : yellow[700],
                    }}
                >
                    {node.type === 'class' ? (
                        <ClassIcon />
                    ) : node.type === 'method' ? (
                        <FunctionsIcon />
                    ) : (
                        <UnionIcon />
                    )}
                </Avatar>
            </ListItemAvatar>
            <ListItemText
                primary={
                    <>
                        {node.prefix}
                        <FuseHighlight
                            matches={matches}
                            value={node.name}
                            className={classes.searchItemMatch}
                        />
                    </>
                }
                secondary={node.type}
            />
        </ListItem>
    )

    const popupContent = (
        <Paper className={classes.popup}>
            {query.length <= 1 || !hits.length ? (
                <div className={classes.popupEmpty}>
                    {query.length <= 1 ? emptyField() : notFound()}
                </div>
            ) : (
                <List disablePadding dense className={classes.popupList}>
                    {hits.map(({ item: { node }, matches }) =>
                        renderSearchItem(node, matches!)
                    )}
                    <div style={{ textAlign: 'center' }}>
                        <Button
                            variant="text"
                            size="small"
                            style={{
                                margin: '4px auto',
                            }}
                            onClick={() => {
                                setIncludeMtproto(!includeMtproto)
                            }}
                        >
                            {includeMtproto ? 'Hide' : 'Include'} MTProto
                            objects
                        </Button>
                    </div>
                </List>
            )}
        </Paper>
    )

    return (
        <ClickAwayListener onClickAway={() => setOpen(false)}>
            <>
                <ActionBarSearchField
                    inputRef={setAnchorEl}
                    autoComplete="off"
                    onFocus={() => setOpen(true)}
                    onBlur={() => setOpen(false)}
                    onChange={onSearch}
                />
                <Popper
                    open={open}
                    anchorEl={anchorEl}
                    placement="bottom"
                    transition
                    style={{
                        width: isMobile ? '100%' : anchorEl?.clientWidth,
                        zIndex: 9999,
                    }}
                >
                    {({ TransitionProps }) => (
                        <Fade {...TransitionProps} timeout={350}>
                            {popupContent}
                        </Fade>
                    )}
                </Popper>
            </>
        </ClickAwayListener>
    )
}
Example #21
Source File: index.tsx    From Demae with MIT License 4 votes vote down vote up
OrderDetail = () => {
	const theme = useTheme()
	const { orderID } = useParams<{ orderID?: string }>()
	const [user] = useUser()
	const ref = user?.orders.collectionReference.doc(orderID)
	const [order, isLoading] = useDocumentListen<Order>(Order, ref)
	const [menuPros, menuOpen] = useMenu()
	const [showDrawer, closeDrawer] = useDrawer()
	const [showSnackbar] = useSnackbar()
	const [setProcessing] = useProcessing()

	if (isLoading || !order) {
		return (
			<Paper>
				<DataLoading />
			</Paper>
		)
	}

	return (
		<>
			<Typography variant="h2" gutterBottom>Order</Typography>
			<Paper style={{
				marginBottom: theme.spacing(2)
			}}>
				<Box padding={2}>
					<Box paddingBottom={2} display="flex" justifyContent="space-between">
						<Box>
							<Typography variant="subtitle1">{order.title}</Typography>
							<Typography variant="body2" color="textSecondary">ORDER ID: {order.id}</Typography>
						</Box>
						<Box>
							<IconButton aria-label="settings" onClick={menuOpen}>
								<MoreVertIcon />
							</IconButton>
							<Menu {...menuPros}>
								{
									order.paymentStatus === "succeeded" ?
										<MenuItem onClick={() => {
											showDrawer(
												<ActionSheet title="Would you like to refund this order?" actions={
													[
														{
															title: "Refund request",
															handler: async () => {
																setProcessing(true)
																const response = await order.refundRequest()
																const { error, result } = response.data
																if (error) {
																	console.error(error)
																	showSnackbar('error', error.message)
																	setProcessing(false)
																	closeDrawer()
																	return
																}
																console.log(result)
																showSnackbar("success", "The order was canceled.")
																setProcessing(false)
																closeDrawer()
															}
														}
													]
												} />
											)
										}}>Refund</MenuItem> :
										<MenuItem onClick={() => {
											showDrawer(
												<ActionSheet title="Would you like to cancel this order?" actions={
													[
														{
															title: "Cancel request",
															handler: async () => {
																setProcessing(true)
																const response = await order.cancel()
																const { error, result } = response.data
																if (error) {
																	console.error(error)
																	showSnackbar('error', error.message)
																	setProcessing(false)
																	closeDrawer()
																	return
																}
																console.log(result)
																showSnackbar("success", "The order was canceled.")
																setProcessing(false)
																closeDrawer()
															}
														}
													]
												} />
											)
										}}>Cancel</MenuItem>
								}

							</Menu>
						</Box>
					</Box>

					<Divider />

					<Box paddingTop={2}>
						<Typography variant="subtitle1" gutterBottom>Items</Typography>
						<Paper>
							<List>
								{order.items.map(data => {
									const image = (data.imageURLs().length > 0) ? data.imageURLs()[0] : undefined
									return (
										<ListItem key={data.skuReference?.path} button component={Link} to={`/providers/${order.providedBy}/products/${data.productReference?.id}/skus/${data.skuReference?.id}`}>
											<ListItemAvatar >
												<Avatar variant="rounded" src={image} style={{
													height: theme.spacing(5),
													width: theme.spacing(5)
												}}>
													<ImageIcon />
												</Avatar>
											</ListItemAvatar>
											<ListItemText primary={
												<>
													<Typography variant="subtitle2">{data.name}</Typography>
													<Typography variant="body2" color="textSecondary">{data.caption}</Typography>
													<Typography variant="body2" color="textSecondary">{data.currency} {data.price.toLocaleString()}</Typography>
												</>
											} secondary={
												<Typography>Qty: {data.quantity.toString()}</Typography>
											} />
										</ListItem>
									)
								})}
							</List>
						</Paper>
						{order.salesMethod === "online" &&
							<Box paddingY={2}>
								<Typography variant="subtitle1" gutterBottom>Shipping Information</Typography>
								<Typography variant="body2" >{order.shipping?.format(["postal_code", "line1", "line2", "city", "state"])}</Typography>
							</Box>
						}
					</Box>

					<Divider />

					<Box paddingTop={2}>
						<Typography variant="subtitle1" gutterBottom>Summary</Typography>
						<Box display="flex" justifyContent="space-between">
							<Typography variant="body1" gutterBottom>Total</Typography>
							<Typography variant="body1" gutterBottom>{order.currency} {order.amount.toLocaleString()}</Typography>
						</Box>
					</Box>
				</Box>
			</Paper>
			<Typography variant="h2" gutterBottom>Shop</Typography>
			<Paper>
				<ProviderInfo order={order} />
			</Paper>
		</>
	)
}