@material-ui/core#CardHeader TypeScript Examples

The following examples show how to use @material-ui/core#CardHeader. 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: Scores.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
ScoresSidebar = ({ score, close }: SidebarProps) => {
  return (
    <ScoresCard elevation={5}>
      <CardHeader
        action={
          <IconButton aria-label="close" onClick={close}>
            <Close />
          </IconButton>
        }
        title="Score"
      />
      <ScoresCardContent>
        <List>
          <Scores score={score} />
        </List>
      </ScoresCardContent>
    </ScoresCard>
  )
}
Example #2
Source File: PreviewPullRequestComponent.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
PreviewPullRequestComponent = (
  props: PreviewPullRequestComponentProps,
) => {
  const { title, description, classes } = props;
  return (
    <Card variant="outlined" className={classes?.card}>
      <CardHeader title={title} subheader="Create a new Pull Request" />
      <CardContent className={classes?.cardContent}>
        <MarkdownContent content={description} />
      </CardContent>
    </Card>
  );
}
Example #3
Source File: SearchCard.tsx    From covid19testing-map with GNU General Public License v3.0 6 votes vote down vote up
SearchCard = () => {
  const classes = useStyles();

  const details: any = [];
  Object.keys(labelMap).forEach((key: string) => {
    details.push({
      type: 'boolean',
      title: labelMap[key].card,
      key,
      icon: labelMap[key].icon,
    });
  });
  return (
    <div>
      <CardHeader title="Search" />

      <CardContent>
        <Typography color="textPrimary" className={classes.cardMargin}>
          Great! Enter the name of their practice or the address of their clinic
          to get started.
        </Typography>
        <Typography color="textPrimary" className={classes.cardMargin}>
          If you can’t find them in our database, it’s unlikely that they are
          offering COVID-19 testing to their patients at this time.
        </Typography>

        <CardActions />
      </CardContent>
    </div>
  );
}
Example #4
Source File: PlayerCard.tsx    From planning-poker with MIT License 6 votes vote down vote up
PlayerCard: React.FC<PlayerCardProps> = ({ game, player }) => {
  return (
    <Card
      variant='outlined'
      className='PlayerCard'
      style={{
        backgroundColor: getCardColor(game, player.value),
      }}
    >
      <CardHeader
        className='PlayerCardTitle'
        title={player.name}
        titleTypographyProps={{ variant: 'subtitle2', noWrap: true }}
      />
      <CardContent className='PlayerCardContent'>
        <Typography variant='h2' className='PlayerCardContentMiddle'>
          {getCardValue(player, game)}
        </Typography>
      </CardContent>
    </Card>
  );
}
Example #5
Source File: Request.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
DocumentRequestCard = ({
  requestBody,
  defaultRequestBody,
  setRequestBody,
}: Props) => {
  let numDocuments = 0

  try {
    const req = JSON.parse(requestBody)
    numDocuments = req.data.length
  } catch (e) {}

  return (
    <DocumentCard>
      <CardHeader
        title={`Documents (${numDocuments})`}
        titleTypographyProps={{ variant: "subtitle1" }}
      />
      <CardContent>
        <DocumentRequest
          defaultRequestBody={defaultRequestBody}
          requestBody={requestBody}
          setRequestBody={setRequestBody}
        />
      </CardContent>
    </DocumentCard>
  )
}
Example #6
Source File: index.tsx    From react-app-architecture with Apache License 2.0 6 votes vote down vote up
AuthorView = ({ author, date }: { author: Author; date?: string }) => {
  const classes = useStyles();
  return (
    <div className={classes.author}>
      {author.profilePicUrl ? (
        <CardHeader
          avatar={<Avatar aria-label={author.name} src={author.profilePicUrl} />}
          title={author.name}
          subheader={date ? convertToReadableDate(date) : ''}
        />
      ) : (
        <CardHeader
          avatar={<FirstLetter text={author.name} />}
          title={author.name}
          subheader={date ? convertToReadableDate(date) : ''}
        />
      )}
    </div>
  );
}
Example #7
Source File: LatestBlock.tsx    From metamask-snap-polkadot with Apache License 2.0 6 votes vote down vote up
LatestBlock = (props: {block: BlockInfo}) => {

    return (
        <Card>
            <CardHeader title="Latest block"/>
            <CardContent>
                <Grid container alignItems="center">
                    <Grid item md={6} xs={12}>
                        <Typography variant="h6">Block number:</Typography>
                        <Typography variant="subtitle2">{props.block.number}</Typography>
                        <Divider light/>
                        <Box m={"0.5rem"}/>
                        <Typography variant="h6">Hash:</Typography>
                        <Typography variant="subtitle2">{props.block.hash}</Typography>
                    </Grid>
                </Grid>
            </CardContent>
        </Card>
    );
}
Example #8
Source File: App.tsx    From react-tutorials with MIT License 6 votes vote down vote up
function App() {
  return (
    <div className="App">
      <header className="App-header">
          <Centered>
              <Card>
                  <CardHeader title="Signup For Our Newsletter" />
                  <CardContent>
                      <SubscribeForm />
                  </CardContent>
              </Card>
          </Centered>
      </header>
    </div>
  )
}
Example #9
Source File: OnCallList.tsx    From backstage-plugin-opsgenie with MIT License 6 votes vote down vote up
OnCallForScheduleCard = ({ schedule }: { schedule: Schedule }) => {
    const title = (
        <div style={{ display: "flex" }}>
            <Tooltip title={schedule.enabled ? 'Enabled' : 'Disabled'}>
                <div>{schedule.enabled ? <StatusOK /> : <StatusAborted />}</div>
            </Tooltip>
            {schedule.ownerTeam.name}
        </div>
    );

    return (
        <Card>
            <CardHeader title={title} titleTypographyProps={{ variant: 'h6' }} />
            <CardContent>
                <OnCallForScheduleList schedule={schedule} />
            </CardContent>
        </Card>
    );
}
Example #10
Source File: Timeline.tsx    From ra-enterprise-demo with MIT License 6 votes vote down vote up
MyTimeline = (): ReactElement => {
    const translate = useTranslate();
    const {
        data: events,
        loaded,
        ids,
    } = useGetList<EventRecord>(
        'events',
        { perPage: 100, page: 1 },
        { field: 'date', order: 'DESC' },
        {}
    );
    const records = ids.map(id => events[id]);
    return (
        <>
            <CardHeader title={translate('pos.dashboard.timeline')} />
            <Timeline loaded={loaded} records={records} />
        </>
    );
}
Example #11
Source File: FlowChartNodes.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
ChartNode = ({
  data,
  selected,
  isDragging,
  type,
}: ChartNodeProps) => {
  const { palette } = useTheme()
  const { item, onScoreClick, hasInput = true, hasOutput = true, name } = data
  const parentId = "parent_id" in item ? item.parent_id : undefined
  const score = "score" in item ? item.score : undefined
  const { id: itemId, uri, mime_type, text } = item
  const elevation = isDragging ? 20 : selected ? 10 : 2

  let style = {}

  if (type === "match")
    style = {
      backgroundColor: palette.filters[0].main,
    }
  else if (type === "chunk")
    style = {
      backgroundColor: palette.filters[3].main,
    }

  return (
    <div>
      {hasInput && <Handle type="source" position={Position.Left}></Handle>}
      <Card elevation={elevation} color="red" style={style}>
        <CardHeader
          style={{ paddingBottom: ".5em" }}
          action={
            score && (
              <Button size="large" onClick={() => onScoreClick(score as Score)}>
                score: {score.value || "0.0"}
              </Button>
            )
          }
        />
        <Box maxWidth="30rem" padding="1em" paddingTop="0em">
          {text && <NodeBigText>"{text}"</NodeBigText>}
          {uri && mimeTypeFromDataURI(uri) && <NodeMediaPreview uri={uri} />}
          <Grid container>
            <Grid item xs={6}>
              {mime_type && (
                <Typography color="textSecondary" gutterBottom>
                  {mime_type}
                </Typography>
              )}
            </Grid>

            <Grid item xs={6}>
              <Box textAlign="right"></Box>
            </Grid>
          </Grid>
          <div style={{ backgroundColor: "#ffffff80" }}>
            <PropertyList data={item} key="main table" />
          </div>

          {parentId && (
            <Box marginTop="0.5rem">
              <Typography color="textSecondary">
                ParentId: {parentId}
              </Typography>
            </Box>
          )}
        </Box>
      </Card>
      {hasOutput && <Handle type="target" position={Position.Right}></Handle>}
    </div>
  )
}
Example #12
Source File: AddShortcut.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
AddShortcut = ({ onClose, anchorEl, api }: Props) => {
  const classes = useStyles();
  const alertApi = useApi(alertApiRef);
  const { pathname } = useLocation();
  const [formValues, setFormValues] = useState<FormValues>();
  const open = Boolean(anchorEl);

  const handleSave: SubmitHandler<FormValues> = async ({ url, title }) => {
    const shortcut: Omit<Shortcut, 'id'> = { url, title };

    try {
      await api.add(shortcut);
      alertApi.post({
        message: `Added shortcut '${title}' to your sidebar`,
        severity: 'success',
      });
    } catch (error) {
      alertApi.post({
        message: `Could not add shortcut: ${error.message}`,
        severity: 'error',
      });
    }

    onClose();
  };

  const handlePaste = () => {
    setFormValues({ url: pathname, title: document.title });
  };

  const handleClose = () => {
    setFormValues(undefined);
    onClose();
  };

  return (
    <Popover
      open={open}
      anchorEl={anchorEl}
      TransitionProps={{ onExit: handleClose }}
      onClose={onClose}
      anchorOrigin={{
        vertical: 'top',
        horizontal: 'right',
      }}
    >
      <Card className={classes.card}>
        <CardHeader
          className={classes.header}
          title="Add Shortcut"
          titleTypographyProps={{ variant: 'subtitle2' }}
          action={
            <Button
              className={classes.button}
              variant="text"
              size="small"
              color="primary"
              onClick={handlePaste}
            >
              Use current page
            </Button>
          }
        />
        <ShortcutForm
          onClose={handleClose}
          onSave={handleSave}
          formValues={formValues}
        />
      </Card>
    </Popover>
  );
}
Example #13
Source File: PricingPlan.tsx    From clearflask with Apache License 2.0 5 votes vote down vote up
render() {
    return (
      <Card elevation={0} className={classNames(this.props.className, this.props.classes.box, this.props.selected && this.props.classes.boxSelected)}>
        <CardHeader
          title={(
            <div className={this.props.classes.title}>
              {this.props.plan.title}
              {this.props.plan.beta && (
                <div className={this.props.classes.beta}>
                  EARLY<br />ACCESS
                </div>
              )}
            </div>
          )}
          titleTypographyProps={{ align: 'center' }}
        />
        <CardContent>
          {this.renderPriceTag()}
          {(this.props.overridePerks || this.props.plan.perks).map(perk => (
            <div key={perk.desc} style={{ display: 'flex', alignItems: 'baseline' }}>
              <CheckIcon fontSize='inherit' />
              &nbsp;
              <Typography variant='subtitle1'>
                {perk.desc}
                {!!perk.terms && (<>
                  &nbsp;
                  <HelpPopper description={perk.terms} />
                </>)}
              </Typography>
            </div>
          ))}
        </CardContent>
        {
          !!this.props.actionTitle && (
            <CardActions className={this.props.classes.actions}>
              {this.props.actionType === 'radio' ? (
                <FormControlLabel
                  label={this.props.actionTitle}
                  control={(
                    <Radio
                      checked={this.props.selected}
                      color='primary'
                      onChange={e => this.props.actionOnClick && this.props.actionOnClick()}
                      disabled={!this.props.actionOnClick}
                    />
                  )}
                />
              ) : (
                <Button
                  color='primary'
                  variant='contained'
                  disableElevation
                  style={{ fontWeight: 900 }}
                  onClick={this.props.actionOnClick}
                  disabled={!this.props.actionOnClick}
                  {...(this.props.actionTo ? {
                    component: Link,
                    to: this.props.actionTo,
                  } : {})}
                  {...(this.props.actionToExt ? {
                    component: 'a',
                    href: this.props.actionToExt,
                  } : {})}
                >
                  {this.props.actionTitle}
                </Button>
              )}
            </CardActions>
          )
        }
        {this.props.remark && (
          <div className={this.props.classes.remark}>
            <Typography variant='caption' component='div' color='textSecondary'>{this.props.remark}</Typography>
          </div>
        )}
      </Card >
    );
  }
Example #14
Source File: StatsCard.component.tsx    From akashlytics with GNU General Public License v3.0 5 votes vote down vote up
export function StatsCard({
  number,
  text,
  tooltip,
  actionButton,
  graphPath,
  diffNumber,
  diffPercent,
}: IStatsCardProps) {
  const classes = useStyles();
  const mediaQuery = useMediaQueryContext();

  return (
    <Card
      className={clsx(classes.root, { [classes.rootSmall]: mediaQuery.smallScreen })}
      elevation={3}
    >
      <CardHeader
        classes={{ title: classes.number, root: classes.cardHeader, subheader: classes.subHeader }}
        title={number}
        subheader={diffNumber && (
          <>
            <DiffNumber value={diffNumber} />
            &nbsp;
            <DiffPercentageChip value={diffPercent} />
          </>
        )}
      />
      <div className={classes.cardContent}>
        <p className={classes.title}>{text}</p>
      </div>

      <CardActions>
        {tooltip && (
          <CustomTooltip arrow enterTouchDelay={0} leaveTouchDelay={10000} title={tooltip}>
            <HelpIcon className={classes.tooltip} />
          </CustomTooltip>
        )}
        {graphPath && (
          <Button
            aria-label="graph"
            component={RouterLink}
            to={graphPath}
            size="small"
            classes={{ label: classes.actionButtonLabel }}
          >
            <Box component="span" marginRight=".5rem">
              Graph
            </Box>
            <TimelineIcon className={classes.actionIcon} />
          </Button>
        )}

        {actionButton}
      </CardActions>
    </Card>
  );
}
Example #15
Source File: RecentGames.tsx    From planning-poker with MIT License 5 votes vote down vote up
RecentGames = () => {
  const history = useHistory();
  const [recentGames, setRecentGames] = useState<Game[] | undefined>(undefined);

  useEffect(() => {
    async function fetchData() {
      const games = await getPlayerRecentGames();
      if (games) {
        setRecentGames(games);
      }
    }
    fetchData();
  }, []);

  const isEmptyRecentGames = (): boolean => {
    if (!recentGames) {
      return true;
    }
    if (recentGames && recentGames.length === 0) {
      return true;
    }
    return false;
  };

  return (
    <Card variant='outlined' className='RecentGamesCard'>
      <CardHeader
        className='RecentGamesCardTitle'
        title='Recent Session'
        titleTypographyProps={{ variant: 'h6', noWrap: true }}
      />
      <CardContent className='RecentGamesCardContent'>
        {isEmptyRecentGames() && (
          <Typography variant='body2'>No recent sessions found</Typography>
        )}
        {recentGames && recentGames.length > 0 && (
          <TableContainer className='RecentGamesTableContainer'>
            <Table stickyHeader>
              <TableHead>
                <TableRow>
                  <TableCell>Name</TableCell>
                  <TableCell>Created By</TableCell>
                  <TableCell></TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {recentGames.map((recentGame) => (
                  <TableRow
                    hover
                    key={recentGame.id}
                    className='RecentGamesTableRow'
                    onClick={() => history.push(`/game/${recentGame.id}`)}
                  >
                    <TableCell>{recentGame.name}</TableCell>
                    <TableCell align='left'>{recentGame.createdBy}</TableCell>
                    <TableCell align='left'></TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
        )}
      </CardContent>
    </Card>
  );
}
Example #16
Source File: Aside.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
ReviewEvent: FC<{ record?: RaRecord; basePath?: string }> = ({
    record,
    basePath,
}) => {
    const translate = useTranslate();
    const classes = useEventStyles();

    if (!record) {
        return null;
    }

    return (
        <Card className={classes.card}>
            <CardHeader
                className={classes.cardHeader}
                avatar={
                    <Avatar
                        aria-label={translate('resources.reviews.name', {
                            smart_count: 1,
                        })}
                    >
                        <review.icon />
                    </Avatar>
                }
                action={<EditButton record={record} basePath="/reviews" />}
                title={
                    <span>
                        {translate('resources.reviews.relative_to_poster')}{' '}
                        <ProductReferenceField
                            resource="reviews"
                            record={record}
                            basePath={basePath}
                        />
                    </span>
                }
                subheader={
                    <>
                        <Typography variant="body2">{record.date}</Typography>
                        <StarRatingField record={record} />
                        <Typography variant="inherit" className={classes.clamp}>
                            {record.comment}
                        </Typography>
                    </>
                }
            />
        </Card>
    );
}
Example #17
Source File: Request.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
Request = ({
  requestBody,
  defaultRequestBody,
  setRequestBody,
}: Props) => {
  const [tab, setTab] = useState(0)

  return (
    <Card>
      <CardHeader
        title="Request Body"
        titleTypographyProps={{ variant: "subtitle1" }}
      />
      <CardContent>
        <Grid container direction={"row"}>
          <Grid item xs={2}>
            <Box p={2}>
              <Tabs
                orientation="vertical"
                aria-label="request type"
                value={tab}
                onChange={(e, v) => setTab(v)}
              >
                <Tab label="Formatted" />
                <Tab label="Raw" />
              </Tabs>
            </Box>
          </Grid>
          <Grid item xs={10}>
            <TabPanel value={tab} index={0}>
              <DocumentRequest
                defaultRequestBody={defaultRequestBody}
                requestBody={requestBody}
                setRequestBody={setRequestBody}
              />
            </TabPanel>
            <TabPanel value={tab} index={1}>
              <TextInput
                id="filled-textarea"
                label="Request body"
                placeholder="Request body"
                multiline
                minRows={10}
                maxRows={20}
                variant="outlined"
                value={requestBody}
                onChange={(e) => setRequestBody(e.target.value)}
              />
            </TabPanel>
          </Grid>
        </Grid>
      </CardContent>
    </Card>
  )
}
Example #18
Source File: SearchResults.tsx    From cognitive-search-static-web-apps-sample-ui with MIT License 5 votes vote down vote up
render(): JSX.Element {

        const state = this.props.state;

        var cards = state.searchResults.map(item => {

            return (
                <Grid key={item.key} item sm={12} md={6}>
                    <Card raised>
                        <CardHeader
                            avatar={
                                <Link onClick={() => state.showDetails(item)}>
                                    <Avatar><FolderIcon /></Avatar>
                                </Link>
                            }
                            title={<Link variant="h6" onClick={() => state.showDetails(item)}>{item.name}</Link>}
                        />                        
                        <CardContent>
                            {item.otherFields.map(val => { return (
                                <Typography variant="body2" key={val}>
                                    {val}
                                </Typography>
                            )})}
                        </CardContent>

                        <TagButtonsDiv>
                            {item.keywords.map(kw => { return (
                                <TagChip
                                    key={kw}
                                    label={kw}
                                    size="small"
                                    onClick={() => state.facetsState.filterBy(item.keywordsFieldName, kw)}
                                    disabled={this.props.inProgress}
                                />
                            ); })}
                        </TagButtonsDiv>

                    </Card>
                </Grid>
            );
        });

        return (<>
            <div>
                <CountersTypography variant="caption" >
                    {state.searchResults.length} of {state.totalResults} results shown 
                </CountersTypography>

                {!!state.inProgress && (<TopLinearProgress />)}
            </div>

            <ResultsGrid container spacing={3}>

                {!!state.errorMessage && (
                    <ErrorChip color="secondary" label={state.errorMessage} onDelete={() => state.HideError()}/>
                )}

                {cards}
            </ResultsGrid>

            {(!!state.inProgress && !!state.searchResults.length) && (<LinearProgress />)}
        </>);
    }
Example #19
Source File: Aside.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
OrderEvent: FC<{ record?: RaRecord; basePath?: string }> = ({
    record,
    basePath,
}) => {
    const translate = useTranslate();
    const classes = useEventStyles();

    if (!record) {
        return null;
    }

    return (
        <Card className={classes.card}>
            <CardHeader
                className={classes.cardHeader}
                avatar={
                    <Avatar
                        aria-label={translate('resources.commands.name', {
                            smart_count: 1,
                        })}
                    >
                        <order.icon />
                    </Avatar>
                }
                action={<EditButton record={record} basePath="/commands" />}
                title={`${translate('resources.commands.name', {
                    smart_count: 1,
                })} #${record.reference}`}
                subheader={
                    <>
                        <Typography variant="body2">{record.date}</Typography>
                        <Typography variant="body2" color="textSecondary">
                            {translate('resources.commands.nb_items', {
                                smart_count: record.basket.length,
                                _: '1 item |||| %{smart_count} items',
                            })}
                            &nbsp;-&nbsp;
                            <NumberField
                                source="total"
                                options={{
                                    style: 'currency',
                                    currency: 'USD',
                                }}
                                record={record}
                                basePath={basePath}
                            />
                            &nbsp;-&nbsp;
                            <TextField
                                source="status"
                                record={record}
                                basePath={basePath}
                            />
                        </Typography>
                    </>
                }
            />
        </Card>
    );
}
Example #20
Source File: SQFormScrollableCardsMenuWrapper.tsx    From SQForm with MIT License 5 votes vote down vote up
export default function SQFormScrollableCardsMenuWrapper({
  title,
  children,
}: SQFormScrollableCardsMenuWrapperProps): JSX.Element {
  const classes = useStyles();

  const menuItems = React.useMemo(
    () =>
      React.Children.map(children, (child) => {
        return {
          label: child.props.label,
          value: child.props.value,
        };
      }),
    [children]
  );

  const [selectedTab, setSelectedTab] = React.useState(() => menuItems[0]);

  const handleChange = (selectedMenuItemValue: string) => {
    const newSelection = menuItems.find(
      (item) => item.value === selectedMenuItemValue
    );

    if (
      typeof newSelection !== 'undefined' &&
      selectedTab.value !== newSelection.value
    ) {
      setSelectedTab(newSelection);
    }
  };

  const SelectedForm = React.useMemo(() => {
    const selected = getSelectedComponent(selectedTab, children);
    return selected;
  }, [selectedTab, children]);

  return (
    <Card raised={true} elevation={1} square={true} className={classes.card}>
      <CardHeader
        classes={{
          action: classes.action,
          title: classes.title,
        }}
        title={title}
        className={classes.cardHeader}
        titleTypographyProps={{variant: 'h5'}}
        action={
          <CardPopoverMenu
            tabs={menuItems}
            selectedTab={selectedTab}
            selectTab={handleChange}
          />
        }
      />
      {SelectedForm}
    </Card>
  );
}
Example #21
Source File: index.tsx    From aqualink-app with MIT License 5 votes vote down vote up
Bleaching = ({ dailyData, classes }: BleachingProps) => {
  const relativeTime = toRelativeTime(dailyData.date);

  return (
    <Card className={classes.root}>
      <CardHeader
        className={classes.header}
        title={
          <Grid container>
            <Grid item xs={12}>
              <Typography
                className={classes.cardTitle}
                color="textSecondary"
                variant="h6"
              >
                HEAT STRESS ALERT LEVEL
              </Typography>
            </Grid>
          </Grid>
        }
      />
      <CardContent className={classes.contentWrapper}>
        <Grid
          className={classes.content}
          container
          alignItems="center"
          alignContent="space-between"
          justify="center"
          item
          xs={12}
        >
          <img
            className={classes.alertImage}
            src={findIntervalByLevel(dailyData.weeklyAlertLevel).image}
            alt="alert-level"
          />
          <UpdateInfo
            relativeTime={relativeTime}
            timeText="Last data received"
            imageText="NOAA CRW"
            live={false}
            frequency="daily"
            href="https://coralsitewatch.noaa.gov/product/5km/index_5km_baa_max_r07d.php"
            withMargin
          />
        </Grid>
      </CardContent>
    </Card>
  );
}
Example #22
Source File: index.tsx    From react-app-architecture with Apache License 2.0 5 votes vote down vote up
BlogCard = ({
  blog,
  selection,
}: {
  blog: Blog;
  selection?: (blog: Blog) => void;
}): ReactElement => {
  const classes = useStyles();

  const { title, description, author, imgUrl, blogUrl, publishedAt } = blog;

  return (
    <Card
      className={classes.card}
      raised={true}
      onClick={() => {
        selection && selection(blog);
      }}
    >
      <CardActionArea className={classes.cardContent} component={Link} to={'/blog/' + blogUrl}>
        <CardMedia
          className={classes.cardMedia}
          component="img"
          alt={title}
          src={imgUrl}
          title={title}
        />
        <CardContent>
          <Typography variant="h6" component="h2" className={classes.cardTitle}>
            {title}
          </Typography>
          <Typography
            variant="body2"
            color="textSecondary"
            component="p"
            className={classes.cardDescription}
          >
            {description}
          </Typography>
        </CardContent>
        <CardHeader
          className={classes.cardAuthor}
          avatar={
            author.profilePicUrl ? (
              <Avatar aria-label={author.name} src={author.profilePicUrl} />
            ) : (
              <FirstLetter text={author.name} />
            )
          }
          title={author.name}
          subheader={convertToReadableDate(publishedAt)}
        />
      </CardActionArea>
    </Card>
  );
}
Example #23
Source File: PullRequestCard.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
PullRequestCard = ({
  pullRequest,
  simplified,
}: PullRequestCardProps) => {
  const title = (
    <Link to={pullRequest.link ?? ''} title={pullRequest.description}>
      {pullRequest.title}
    </Link>
  );

  const repoLink = (
    <Link to={pullRequest.repository?.url ?? ''} color="inherit">
      {pullRequest.repository?.name}
    </Link>
  );

  const creationDate = pullRequest.creationDate
    ? DateTime.fromISO(pullRequest.creationDate).toRelative()
    : undefined;

  const subheader = (
    <span>
      {repoLink} · {creationDate}
    </span>
  );

  const avatar = (
    <Avatar
      displayName={pullRequest.createdBy?.displayName}
      picture={pullRequest.createdBy?.imageUrl}
      customStyles={{ width: '2.5rem', height: '2.5rem', fontSize: '1rem' }}
    />
  );

  const classes = useStyles();

  return (
    <Card
      classes={{ root: classes.card }}
      data-pull-request-id={pullRequest.pullRequestId}
    >
      <CardHeader
        avatar={avatar}
        title={title}
        subheader={subheader}
        action={
          <AutoCompleteIcon hasAutoComplete={pullRequest.hasAutoComplete} />
        }
        classes={{
          ...(simplified && { root: classes.cardHeaderSimplified }),
          action: classes.cardHeaderAction,
        }}
      />

      {!simplified && (
        <CardContent className={classes.content}>
          {pullRequest.policies && (
            <PullRequestCardPolicies
              policies={pullRequest.policies}
              className={classes.policies}
            />
          )}

          {pullRequest.reviewers && (
            <PullRequestCardReviewers reviewers={pullRequest.reviewers} />
          )}
        </CardContent>
      )}
    </Card>
  );
}
Example #24
Source File: index.tsx    From react-app-architecture with Apache License 2.0 5 votes vote down vote up
InfoCard = ({
  imgUrl,
  href,
  title,
  subtitle,
  description,
  action = 'Learn More',
}: {
  imgUrl: string;
  href: string;
  title: string;
  subtitle: string;
  description: string;
  action?: string;
}) => {
  const classes = useStyles();
  return (
    <Card className={classes.infoCard} raised={true}>
      <CardHeader
        avatar={<Avatar className={classes.avatar} src={imgUrl} />}
        title={title}
        subheader={subtitle}
      />
      <CardContent>
        <Typography variant="subtitle1" component="p">
          {description}
        </Typography>
      </CardContent>
      <CardActions className={classes.cardAction}>
        <Button
          className={classes.button}
          variant="contained"
          component="a"
          size="small"
          color="primary"
          href={href}
          target="_blank"
        >
          {action}
        </Button>
      </CardActions>
    </Card>
  );
}
Example #25
Source File: FileList.tsx    From aqualink-app with MIT License 5 votes vote down vote up
FileList = ({ files, onFileDelete }: FileListProps) => {
  const classes = useStyles();
  const errors = useSelector(uploadsErrorSelector) as Record<
    string,
    string | null
  >;
  const loading = useSelector(uploadsInProgressSelector);
  const uploadResponse = useSelector(uploadsResponseSelector);

  return (
    <Grid container spacing={2} className={classes.root}>
      <Grid item xs={12}>
        <Typography gutterBottom variant="h6">
          {files.length} {pluralize(files.length, "file")}{" "}
          {loading ? "uploading" : "to be uploaded"}
        </Typography>
      </Grid>
      {files.map(({ name }) => (
        <Grid item key={name} lg={4} md={6} xs={12}>
          <Card className={classes.card} variant="outlined">
            <CardHeader
              className={classNames({ [classes.loading]: loading })}
              classes={{ content: classes.cardContent }}
              title={
                <Typography
                  className={classes.cardHeaderTitle}
                  title={name}
                  color="textSecondary"
                  variant="h6"
                >
                  {name}
                </Typography>
              }
              action={
                <Tooltip title="Remove file" arrow placement="top">
                  <IconButton
                    disabled={loading}
                    onClick={() => onFileDelete(name)}
                  >
                    <CloseIcon />
                  </IconButton>
                </Tooltip>
              }
              avatar={<FileIcon className={classes.fileIcon} />}
            />
            {loading && (
              <CircularProgress
                size={CIRCULAR_PROGRESS_SIZE}
                className={classes.circularProgress}
              />
            )}
          </Card>
          {errors?.[name] && <Alert severity="error">{errors[name]}</Alert>}
          {!loading &&
            !!uploadResponse?.some((x) => x.file === name && !x.error) && (
              <Alert severity="success">File uploaded</Alert>
            )}
        </Grid>
      ))}
    </Grid>
  );
}
Example #26
Source File: GameController.tsx    From planning-poker with MIT License 4 votes vote down vote up
GameController: React.FC<GameControllerProps> = ({ game, currentPlayerId }) => {
  const history = useHistory();
  const [showCopiedMessage, setShowCopiedMessage] = useState(false);
  const copyInviteLink = () => {
    const dummy = document.createElement('input');
    const url = `${window.location.origin}/join/${game.id}`;
    document.body.appendChild(dummy);
    dummy.value = url;
    dummy.select();
    document.execCommand('copy');
    document.body.removeChild(dummy);
    setShowCopiedMessage(true);
  };

  const leaveGame = () => {
    history.push(`/`);
  };

  const isModerator = (moderatorId: string, currentPlayerId: string) => {
    return moderatorId === currentPlayerId;
  };
  return (
    <Grow in={true} timeout={2000}>
      <div className='GameController'>
        <Card variant='outlined' className='GameControllerCard'>
          <CardHeader
            title={game.name}
            titleTypographyProps={{ variant: 'h6' }}
            action={
              <div className='GameControllerCardHeaderAverageContainer'>
                <Typography variant='subtitle1'>{game.gameStatus}</Typography>
                {game.gameType !== GameType.TShirt && (
                  <>
                    <Divider className='GameControllerDivider' orientation='vertical' flexItem />
                    <Typography variant='subtitle1'>Average:</Typography>
                    <Typography variant='subtitle1' className='GameControllerCardHeaderAverageValue'>
                      {game.average || 0}
                    </Typography>
                  </>
                )}
              </div>
            }
            className='GameControllerCardTitle'
          ></CardHeader>
          <CardContent className='GameControllerCardContentArea'>
            {isModerator(game.createdById, currentPlayerId) && (
              <>
                <div className='GameControllerButtonContainer'>
                  <div className='GameControllerButton'>
                    <IconButton onClick={() => finishGame(game.id)} data-testid='reveal-button' color='primary'>
                      <VisibilityIcon fontSize='large' style={{ color: green[500] }} />
                    </IconButton>
                  </div>
                  <Typography variant='caption'>Reveal</Typography>
                </div>

                <div className='GameControllerButtonContainer'>
                  <div className='GameControllerButton'>
                    <IconButton data-testid={'restart-button'} onClick={() => resetGame(game.id)}>
                      <RefreshIcon fontSize='large' color='error' />
                    </IconButton>
                  </div>
                  <Typography variant='caption'>Restart</Typography>
                </div>
              </>
            )}
            <div className='GameControllerButtonContainer'>
              <div className='GameControllerButton'>
                <IconButton data-testid='exit-button' onClick={() => leaveGame()}>
                  <ExitToApp fontSize='large' style={{ color: orange[500] }} />
                </IconButton>
              </div>
              <Typography variant='caption'>Exit</Typography>
            </div>
            <div title='Copy invite link' className='GameControllerButtonContainer'>
              <div className='GameControllerButton'>
                <IconButton data-testid='invite-button' onClick={() => copyInviteLink()}>
                  <LinkIcon fontSize='large' style={{ color: blue[500] }} />
                </IconButton>
              </div>
              <Typography variant='caption'>Invite</Typography>
            </div>
          </CardContent>
        </Card>
        <Snackbar
          anchorOrigin={{ horizontal: 'right', vertical: 'top' }}
          open={showCopiedMessage}
          autoHideDuration={5000}
          onClose={() => setShowCopiedMessage(false)}
        >
          <Alert severity='success'>Invite Link copied to clipboard!</Alert>
        </Snackbar>
      </div>
    </Grow>
  );
}
Example #27
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
Sensor = ({ depth, id, data, classes }: SensorProps) => {
  const { topTemperature, bottomTemperature } = data;

  const relativeTime =
    (topTemperature?.timestamp && toRelativeTime(topTemperature.timestamp)) ||
    (bottomTemperature?.timestamp &&
      toRelativeTime(bottomTemperature.timestamp));

  const hasSpotter = Boolean(topTemperature?.value || bottomTemperature?.value);

  const user = useSelector(userInfoSelector);

  const metrics = [
    {
      label: "TEMP AT 1m",
      value: `${formatNumber(topTemperature?.value, 1)}°C`,
    },
    {
      label: `TEMP AT ${depth ? `${depth}m` : "DEPTH"}`,
      value: `${formatNumber(bottomTemperature?.value, 1)}°C`,
    },
  ];

  const [alertText, clickable] = getApplicationTag(user, id);

  return (
    <Card className={classes.root}>
      <CardHeader
        className={classes.header}
        title={
          <Grid container>
            <Grid item>
              <Typography className={classes.cardTitle} variant="h6">
                BUOY OBSERVATION
              </Typography>
            </Grid>
          </Grid>
        }
      />

      <CardContent className={classes.content}>
        <Box
          p="1rem"
          display="flex"
          flexGrow={1}
          style={{ position: "relative" }}
        >
          <Grid container spacing={1}>
            {metrics.map(({ label, value }) => (
              <Grid key={label} item xs={12}>
                <Typography
                  className={classes.contentTextTitles}
                  variant="subtitle2"
                >
                  {label}
                </Typography>
                <Typography className={classes.contentTextValues} variant="h3">
                  {value}
                </Typography>
              </Grid>
            ))}
          </Grid>

          <Box position="absolute" bottom={-15} right={0}>
            <img alt="sensor" src={sensor} />
          </Box>
        </Box>
        {hasSpotter ? (
          <UpdateInfo
            relativeTime={relativeTime}
            timeText="Last data received"
            live
            frequency="hourly"
            withMargin
          />
        ) : (
          <Grid
            className={classes.noSensorAlert}
            container
            alignItems="center"
            justify="center"
          >
            {clickable ? (
              <Link
                className={classes.newSpotterLink}
                to={`/sites/${id}/apply`}
              >
                <Typography variant="h6">{alertText}</Typography>
              </Link>
            ) : (
              <Typography variant="h6">{alertText}</Typography>
            )}
          </Grid>
        )}
      </CardContent>
    </Card>
  );
}
Example #28
Source File: JoinGame.tsx    From planning-poker with MIT License 4 votes vote down vote up
JoinGame = () => {
  const history = useHistory();
  let { id } = useParams<{ id: string }>();

  const [joinGameId, setJoinGameId] = useState(id);
  const [playerName, setPlayerName] = useState('');
  const [gameFound, setIsGameFound] = useState(true);

  useEffect(() => {
    async function fetchData() {
      if (joinGameId) {
        if (await getGame(joinGameId)) {
          setIsGameFound(true);
          if (isCurrentPlayerInGame(joinGameId)) {
            history.push(`/game/${joinGameId}`);
          }
        }
      }
    }
    fetchData();
  }, [joinGameId, history]);

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault();
    if (joinGameId) {
      const res = await addPlayerToGame(joinGameId, playerName);

      setIsGameFound(res);
      if (res) {
        history.push(`/game/${joinGameId}`);
      }
    }
  };

  return (
    <Grow in={true} timeout={500}>
      <div>
        <form onSubmit={handleSubmit}>
          <Card variant='outlined' className='JoinGameCard'>
            <CardHeader
              className='JoinGameCardHeader'
              title='Join a Session'
              titleTypographyProps={{ variant: 'h4' }}
            />
            <CardContent className='JoinGameCardContent'>
              <TextField
                error={!gameFound}
                helperText={!gameFound && 'Session not found, check the ID'}
                className='JoinGameTextField'
                required
                id='filled-required'
                label='Session ID'
                placeholder='xyz...'
                defaultValue={joinGameId}
                variant='outlined'
                onChange={(event: ChangeEvent<HTMLInputElement>) =>
                  setJoinGameId(event.target.value)
                }
              />
              <TextField
                className='JoinGameTextField'
                required
                id='filled-required'
                label='Your Name'
                placeholder='Enter your name'
                defaultValue={playerName}
                variant='outlined'
                onChange={(event: ChangeEvent<HTMLInputElement>) =>
                  setPlayerName(event.target.value)
                }
              />
            </CardContent>
            <CardActions className='JoinGameCardAction'>
              <Button
                type='submit'
                variant='contained'
                color='primary'
                className='JoinGameButton'
              >
                Join
              </Button>
            </CardActions>
          </Card>
        </form>
      </div>
    </Grow>
  );
}
Example #29
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
Satellite = ({ maxMonthlyMean, data, classes }: SatelliteProps) => {
  const { dhw, satelliteTemperature, sstAnomaly } = data;
  const degreeHeatingDays = { ...dhw, value: (dhw?.value || 0) * 7 };
  const relativeTime =
    satelliteTemperature?.timestamp &&
    toRelativeTime(satelliteTemperature.timestamp);

  const degreeHeatingWeeks = degreeHeatingWeeksCalculator(
    degreeHeatingDays?.value
  );

  const metrics = [
    {
      label: "SURFACE TEMP",
      value: `${formatNumber(satelliteTemperature?.value, 1)}°C`,
    },
    {
      label: "HISTORICAL MAX",
      value: `${formatNumber(maxMonthlyMean, 1)}°C`,
      tooltipTitle: "Historical maximum monthly average over the past 20 years",
    },
    {
      label: "DEGREE HEATING WEEKS",
      value: formatNumber(degreeHeatingWeeks, 1),
      tooltipTitle:
        "Degree Heating Weeks - a measure of the amount of time above the 20 year historical maximum temperatures",
    },
    {
      label: "SST ANOMALY",
      tooltipTitle: "Difference between current SST and longterm average",
      value: `${
        sstAnomaly
          ? `${sstAnomaly.value > 0 ? "+" : ""}${formatNumber(
              sstAnomaly.value,
              1
            )}`
          : "- -"
      }°C`,
    },
  ];

  return (
    <Card
      className={classes.root}
      style={{ backgroundColor: dhwColorFinder(degreeHeatingWeeks) }}
    >
      <CardHeader
        className={classes.header}
        title={
          <Grid container>
            <Grid item>
              <Typography className={classes.cardTitle} variant="h6">
                SATELLITE OBSERVATION
              </Typography>
            </Grid>
          </Grid>
        }
      />

      <CardContent className={classes.content}>
        <Box p="1rem" display="flex" flexGrow={1}>
          <Grid container spacing={1}>
            {metrics.map(({ label, value, tooltipTitle }) => (
              <Grid key={label} item xs={6}>
                <Typography
                  className={classes.contentTextTitles}
                  variant="subtitle2"
                >
                  {label}
                </Typography>
                <Tooltip title={tooltipTitle || ""}>
                  <Typography
                    className={classes.contentTextValues}
                    variant="h3"
                  >
                    {value}
                  </Typography>
                </Tooltip>
              </Grid>
            ))}
          </Grid>
        </Box>

        <Grid container>
          {dhwColorCode.map(({ value, color }) => (
            <Grid
              key={value}
              item
              xs={1}
              style={{ backgroundColor: `${color}`, height: "2rem" }}
            >
              <Box textAlign="center">
                <Typography variant="caption" align="center">
                  {value}
                </Typography>
              </Box>
            </Grid>
          ))}
        </Grid>

        <UpdateInfo
          relativeTime={relativeTime}
          timeText="Last data received"
          image={satellite}
          imageText="NOAA"
          live={false}
          frequency="daily"
          href="https://coralsitewatch.noaa.gov/"
        />
      </CardContent>
    </Card>
  );
}