@mui/icons-material#Favorite TypeScript Examples

The following examples show how to use @mui/icons-material#Favorite. 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: CharacterSelectionModal.tsx    From genshin-optimizer with MIT License 6 votes vote down vote up
function CharacterBtn({ onClick, characterKey, characterSheet }: { onClick: () => void, characterKey: CharacterKey, characterSheet: CharacterSheet }) {
  const teamData = useTeamData(characterKey)
  const { database } = useContext(DatabaseContext)
  const characterDispatch = useCharacterReducer(characterKey)
  const favorite = database._getChar(characterKey)?.favorite
  const { target: data } = teamData?.[characterKey] ?? {}
  const rarity = characterSheet.rarity
  return <Suspense fallback={<Skeleton variant="rectangular" height={130} />}><Box>
    {favorite !== undefined && <Box display="flex" position="absolute" alignSelf="start" zIndex={1}>
      <IconButton sx={{ p: 0.5 }} onClick={() => characterDispatch({ favorite: !favorite })}>
        {favorite ? <Favorite /> : <FavoriteBorder />}
      </IconButton>
    </Box>}
    <CardActionArea onClick={onClick} >
      <CardLight sx={{ display: "flex", alignItems: "center" }}  >
        <Box component="img" src={characterSheet.thumbImg} sx={{ width: 130, height: "auto" }} className={`grad-${rarity}star`} />
        <Box sx={{ pl: 1 }}>
          <Typography><strong>{characterSheet.name}</strong></Typography>
          {data ? <>
            <Typography variant="h6"> {characterSheet.elementKey && StatIcon[characterSheet.elementKey]} <ImgIcon src={Assets.weaponTypes?.[characterSheet.weaponTypeKey]} />{` `}{CharacterSheet.getLevelString(data.get(input.lvl).value, data.get(input.asc).value)}</Typography>
            <Typography >
              <SqBadge color="success">{`C${data.get(input.constellation).value}`}</SqBadge>{` `}
              <SqBadge color={data.get(input.bonus.auto).value ? "info" : "secondary"}><strong >{data.get(input.total.auto).value}</strong></SqBadge>{` `}
              <SqBadge color={data.get(input.bonus.skill).value ? "info" : "secondary"}><strong >{data.get(input.total.skill).value}</strong></SqBadge>{` `}
              <SqBadge color={data.get(input.bonus.burst).value ? "info" : "secondary"}><strong >{data.get(input.total.burst).value}</strong></SqBadge>
            </Typography>
          </> : <>
            <Typography variant="h6"><SqBadge color="primary">NEW</SqBadge></Typography>
          </>}
          <small><Stars stars={rarity} colored /></small>
        </Box>
      </CardLight>
    </CardActionArea >
  </Box></Suspense>
}
Example #2
Source File: CharacterCard.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
export default function CharacterCard({ characterKey, artifactChildren, weaponChildren, characterChildren, onClick, onClickHeader, footer, isTeammateCard }: CharacterCardProps) {
  const { teamData: teamDataContext } = useContext(DataContext)
  const teamData = useTeamData(teamDataContext ? "" : characterKey) ?? (teamDataContext as TeamData | undefined)
  const { character, characterSheet, target: data } = teamData?.[characterKey] ?? {}
  const onClickHandler = useCallback(() => characterKey && onClick?.(characterKey, "overview"), [characterKey, onClick])
  const actionWrapperFunc = useCallback(
    children => <CardActionArea onClick={onClickHandler} sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }}>{children}</CardActionArea>,
    [onClickHandler],
  )
  const characterDispatch = useCharacterReducer(characterKey)
  if (!teamData || !character || !characterSheet || !data) return null;
  const dataContextObj: dataContextObj = {
    character,
    data,
    characterSheet,
    mainStatAssumptionLevel: 0,
    teamData,
    characterDispatch
  }

  return <Suspense fallback={<Skeleton variant="rectangular" sx={{ width: "100%", height: "100%", minHeight: 350 }} />}>
    <DataContext.Provider value={dataContextObj}>
      <CardLight sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
        <Box sx={{ display: "flex", position: "absolute", zIndex: 2, opacity: 0.7 }}>
          <IconButton sx={{ p: 0.5 }} onClick={event => characterDispatch({ favorite: !character.favorite })}>
            {character.favorite ? <Favorite /> : <FavoriteBorder />}
          </IconButton>
        </Box>
        <ConditionalWrapper condition={!!onClick} wrapper={actionWrapperFunc} >
          <Header onClick={!onClick ? onClickHeader : undefined} />
          <CardContent sx={{ width: "100%", display: "flex", flexDirection: "column", gap: 1, flexGrow: 1 }}>
            <Artifacts />
            {!isTeammateCard && <Grid container columns={4} spacing={0.75}>
              <Grid item xs={1} height="100%">
                <WeaponCardPico weaponId={character.equippedWeapon} />
              </Grid>
              {range(0, 2).map(i => <Grid key={i} item xs={1} height="100%"><CharacterCardPico characterKey={character.team[i]} index={i} /></Grid>)}
            </Grid>}
            {isTeammateCard && <WeaponFullCard weaponId={character.equippedWeapon} />}
            {!isTeammateCard && <Stats />}
            {weaponChildren}
            {artifactChildren}
            {characterChildren}
          </CardContent>
        </ConditionalWrapper>
        {footer}
      </CardLight>
    </DataContext.Provider>
  </Suspense>
}
Example #3
Source File: CampaignCard.tsx    From frontend with MIT License 5 votes vote down vote up
export default function CampaignCard({ campaign }: Props) {
  const { t } = useTranslation()

  const target = campaign.targetAmount
  const summary = campaign.summary.find(() => true)
  const pictureUrl = campaignListPictureUrl(campaign)
  const reached = summary ? summary.reachedAmount : 0

  return (
    <StyledCard variant="outlined" className={classes.cardWrapper}>
      <CardActionArea>
        <Link href={routes.campaigns.viewCampaignBySlug(campaign.slug)}>
          <CardMedia
            className={classes.media}
            image={pictureUrl}
            title="campaign image placeholder"
          />
        </Link>
        <CardContent className={classes.cardContent}>
          <Typography textAlign={'left'} gutterBottom variant="h5" component="h2">
            {campaign.title}
          </Typography>
          <Typography textAlign={'left'} variant="body2" color="textSecondary" component="p">
            {campaign.essence}
          </Typography>
        </CardContent>
      </CardActionArea>
      <CardActions className={classes.cardActions}>
        <Grid container justifyContent="space-around">
          <Box p={2} width={1}>
            <CampaignProgress raised={reached} target={target} />
          </Box>
          <Typography variant="subtitle1" component="p" className={classes.progressBar}>
            {t('campaigns:campaign.reached')} <b>{money(reached)}</b> /{' '}
            {t('campaigns:campaign.target')} <b>{money(target)}</b>
          </Typography>
          <Grid item xs={12}>
            <Box mx={2} mb={2}>
              <LinkButton
                fullWidth
                href={routes.campaigns.oneTimeDonation(campaign.slug)}
                variant="contained"
                color="secondary"
                endIcon={<Favorite color="error" />}>
                {t('campaigns:cta.support-now')}
              </LinkButton>
            </Box>
            <Box mx={2} mb={2}>
              <LinkButton
                fullWidth
                href={routes.campaigns.viewCampaignBySlug(campaign.slug)}
                variant="outlined"
                endIcon={<ArrowForwardIosIcon />}>
                {t('campaigns:cta.see-more')}
              </LinkButton>
            </Box>
          </Grid>
        </Grid>
      </CardActions>
    </StyledCard>
  )
}
Example #4
Source File: CharacterAutocomplete.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function CharacterAutocomplete({ value, onChange, defaultText = "", defaultIcon = "", placeholderText = "", labelText = "", showDefault = false, showInventory = false, showEquipped = false, filter = () => true, disable = () => false, ...props }: CharacterAutocompleteProps) {
  // TODO: #412 We shouldn't be loading all the character translation files. Should have a separate lookup file for character name.
  const { t } = useTranslation(["ui", "artifact", ...allCharacterKeys.map(k => `char_${k}_gen`)])
  const theme = useTheme()
  const { database } = useContext(DatabaseContext)
  const characterSheets = usePromise(CharacterSheet.getAll, [])
  const filterConfigs = useMemo(() => characterSheets && characterFilterConfigs(database, characterSheets), [database, characterSheets])
  const characterKeys = database._getCharKeys().filter(ck => characterSheets?.[ck] && filter(characterSheets[ck], ck)).sort()

  const textForValue = useCallback((value: CharacterAutocompleteValue): string => {
    switch (value) {
      case "Equipped":
        return t("artifact:filterLocation.currentlyEquipped")
      case "Inventory":
        return t("artifact:filterLocation.inventory")
      case "":
        return defaultText
      default:
        return t(`char_${value}_gen:name`)
    }
  }, [defaultText, t])

  const imageForValue = useCallback((value: CharacterAutocompleteValue): Displayable => {
    switch (value) {
      case "Equipped":
        return <FontAwesomeIcon icon={faUserShield} />
      case "Inventory":
        return <BusinessCenter />
      case "":
        return defaultIcon
      default:
        return <ThumbSide src={characterSheets![value]?.thumbImgSide} sx={{ pr: 1 }} />
    }
  }, [defaultIcon, characterSheets])

  const characterOptions = useMemo(() => filterConfigs && charOptions(characterKeys, filterConfigs, textForValue, showDefault, showInventory, showEquipped),
    [filterConfigs, characterKeys, showDefault, showInventory, showEquipped, textForValue])



  if (!characterSheets || !characterOptions) return null

  return <Autocomplete
    autoHighlight
    options={characterOptions}
    getOptionLabel={(option) => option.label}
    onChange={(_, newValue) => onChange(newValue ? newValue.value : "")}
    isOptionEqualToValue={(option, value) => option.value === value.value}
    getOptionDisabled={option => option.value ? disable(option.value) : false}
    value={{ value, label: textForValue(value) }}
    renderInput={(props) => <SolidColoredTextField
      {...props}
      label={labelText}
      placeholder={placeholderText}
      startAdornment={imageForValue(value)}
      hasValue={value ? true : false}
    />}
    renderOption={(props, option) => {
      const favorite = option.value !== "Equipped" && option.value !== "Inventory"
        && option.value !== "" && database._getChar(option.value)?.favorite
      return <MenuItemWithImage
        key={option.value ? option.value : "default"}
        value={option.value ? option.value : "default"}
        image={imageForValue(option.value)}
        text={
          <Suspense fallback={<Skeleton variant="text" width={100} />}>
            <Typography variant="inherit" noWrap>
              {textForValue(option.value)}
            </Typography>
          </Suspense>
        }
        theme={theme}
        isSelected={value === option.value}
        addlElement={<>
          {favorite && <Box display="flex" flexGrow={1} />}
          {favorite && <Favorite sx={{ ml: 1, mr: -0.5 }} />}
        </>}
        props={props}
      />
    }}
    {...props}
  />
}
Example #5
Source File: TabOverview.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function TabOverview() {
  const { data, characterSheet, character, character: { key: characterKey } } = useContext(DataContext)
  const characterDispatch = useCharacterReducer(characterKey)
  const navigate = useNavigate()
  const { t } = useTranslation("page_character")
  const charEle = data.get(input.charEle).value as ElementKey
  const weaponTypeKey = characterSheet.weaponTypeKey
  const level = data.get(input.lvl).value
  const ascension = data.get(input.asc).value
  const constellation = data.get(input.constellation).value
  const tlvl = {
    auto: data.get(input.total.auto).value,
    skill: data.get(input.total.skill).value,
    burst: data.get(input.total.burst).value,
  }
  const tBoost = {
    auto: data.get(input.bonus.auto).value,
    skill: data.get(input.bonus.skill).value,
    burst: data.get(input.bonus.burst).value,
  }
  return <Grid container spacing={1} sx={{ justifyContent: "center" }}>
    <Grid item xs={8} sm={5} md={4} lg={2.5}  >
      {/* Image card with star and name and level */}
      <CardLight >
        <Box src={characterSheet.cardImg} component="img" width="100%" height="auto" />
        <CardContent>
          <Typography variant="h5" >
            {characterSheet.name}&nbsp;
            <ImgIcon sx={{ pr: 0.5 }} src={Assets.weaponTypes?.[weaponTypeKey]} />
            {StatIcon[charEle]}
            <IconButton sx={{ p: 0.5, mt: -0.5 }} onClick={() => characterDispatch({ favorite: !character.favorite })}>
              {character.favorite ? <Favorite /> : <FavoriteBorder />}
            </IconButton>
          </Typography>
          <Typography variant="h6"><Stars stars={characterSheet.rarity} colored /></Typography>
          <Typography variant="h5">Lvl. {CharacterSheet.getLevelString(level, ascension)}</Typography>
          <CardActionArea sx={{ p: 1 }} onClick={() => navigate("talent")}>
            <Grid container spacing={1} mt={-1}>
              {(["auto", "skill", "burst"] as TalentSheetElementKey[]).map(tKey =>
                <Grid item xs={4} key={tKey}>
                  <Badge badgeContent={tlvl[tKey]} color={tBoost[tKey] ? "info" : "secondary"}
                    overlap="circular"
                    anchorOrigin={{
                      vertical: 'bottom',
                      horizontal: 'right',
                    }}
                    sx={{
                      width: "100%",
                      height: "100%",
                      "& > .MuiBadge-badge": {
                        fontSize: "1.25em",
                        padding: ".25em .4em",
                        borderRadius: ".5em",
                        lineHeight: 1,
                        height: "1.25em"
                      }
                    }}>
                    <Box component="img" src={characterSheet.getTalentOfKey(tKey, charEle)?.img} width="100%" height="auto" />
                  </Badge>
                </Grid>)}
            </Grid>
          </CardActionArea>
          <Typography sx={{ textAlign: "center", mt: 1 }} variant="h6">{characterSheet.constellationName}</Typography>
          <Grid container spacing={1}>
            {range(1, 6).map(i =>
              <Grid item xs={4} key={i}>
                <CardActionArea onClick={() => characterDispatch({ constellation: i === constellation ? i - 1 : i })}>
                  <Box component="img" src={characterSheet.getTalentOfKey(`constellation${i}` as TalentSheetElementKey, charEle)?.img}
                    sx={{
                      ...(constellation >= i ? {} : { filter: "brightness(50%)" })
                    }}
                    width="100%" height="auto" />
                </CardActionArea>
              </Grid>)}
          </Grid>
          <Typography sx={{ textAlign: "center", mt: 1 }} variant="h6">{t("teammates")}</Typography>
          <CardActionArea sx={{ p: 1 }} onClick={() => navigate("teambuffs")}>
            <Grid container columns={3} spacing={1}>
              {range(0, 2).map(i => <Grid key={i} item xs={1} height="100%"><CharacterCardPico characterKey={character.team[i]} index={i} /></Grid>)}
            </Grid>
          </CardActionArea>
        </CardContent>
      </CardLight>
    </Grid>
    <Grid item xs={12} sm={7} md={8} lg={9.5} sx={{
      display: "flex", flexDirection: "column", gap: 1
    }} >
      <Grid container spacing={1} columns={{ xs: 2, sm: 2, md: 3, lg: 4, xl: 6 }}>
        <Grid item xs={1}>
          <WeaponCardNano weaponId={character.equippedWeapon} BGComponent={CardLight} onClick={() => navigate("equip")} />
        </Grid>
        {allSlotKeys.map(slotKey =>
          <Grid item key={slotKey} xs={1} >
            <ArtifactCardNano artifactId={data.get(input.art[slotKey].id).value} slotKey={slotKey} BGComponent={CardLight} onClick={() => navigate("equip")} />
          </Grid>)}
      </Grid>
      <MainStatsCards />
    </Grid>
  </Grid >
}
Example #6
Source File: InlineDonation.tsx    From frontend with MIT License 4 votes vote down vote up
export default function InlineDonation({ campaign }: Props) {
  const { t } = useTranslation()
  const router = useRouter()
  const [showDonationPriceList, setDonationPriceList] = useState(false)
  const onClick = () => setDonationPriceList(true)

  const target = campaign.targetAmount
  const summary = campaign.summary.find(() => true)
  const reached = summary?.reachedAmount ?? 0
  const donors = summary?.donors ?? 0
  const { data: prices } = useSinglePriceList()
  const {
    data: donations,
    error: donationHistoryError,
    isLoading: isDonationHistoryLoading,
  } = useCampaignDonationHistory(campaign.id)

  const sortedPrices = useMemo(() => {
    if (!prices) return []
    return prices?.sort((a, b) => {
      if (a.unit_amount === null || b.unit_amount === null) return 0
      return a.unit_amount - b.unit_amount
    })
  }, [prices])
  return (
    <StyledGrid item xs={12} mt={5} p={3} className={classes.inlineDonationWrapper}>
      <Grid mb={2}>
        <Typography component="span" className={classes.reachedMoney}>
          {money(reached)}
        </Typography>{' '}
        {t('campaigns:campaign.from')}{' '}
        <Typography component="span" className={classes.targetMoney}>
          {money(target)}
        </Typography>
      </Grid>
      <CampaignProgress raised={reached} target={target} />
      <Grid display="inline-block" m={3} ml={0}>
        <Typography className={classes.donorsSharesCount}>{donors}</Typography>
        <Typography>{t('campaigns:campaign.donors')}</Typography>
      </Grid>
      <Grid display="inline-block" m={3} ml={0}>
        <Typography className={classes.donorsSharesCount}>{0}</Typography>
        <Typography>{t('campaigns:campaign.shares')}</Typography>
      </Grid>
      <Grid container gap={2}>
        <LinkButton
          fullWidth
          href="#"
          variant="outlined"
          startIcon={<ShareIcon />}
          color="secondary">
          {t('campaigns:cta.share')}
        </LinkButton>
        <LinkButton
          fullWidth
          href="#"
          onClick={onClick}
          variant="contained"
          color="secondary"
          startIcon={<Favorite color="action" />}>
          {t('common:support')}
        </LinkButton>
        {showDonationPriceList && (
          <List className={classes.donationPriceList}>
            {sortedPrices.map((price, index) => {
              if (!price) return null
              return (
                <ListItem button key={index}>
                  <ListItemText
                    onClick={() =>
                      router.push({
                        pathname: routes.campaigns.oneTimeDonation(campaign.slug),
                        query: {
                          price: price.id,
                        },
                      })
                    }
                    primary={`${(price.unit_amount ?? 100) / 100} лв.`}
                    secondary={price.metadata.title}
                  />
                </ListItem>
              )
            })}
          </List>
        )}
      </Grid>
      {donationHistoryError ? (
        'Error fetching donation history'
      ) : isDonationHistoryLoading ? (
        <CircularProgress sx={{ display: 'block', margin: `${theme.spacing(3)} auto` }} />
      ) : (
        <DonorsAndDonations donations={donations} />
      )}
      {/* <pre>{JSON.stringify(prices, null, 2)}</pre> */}
    </StyledGrid>
  )
}