react-icons/fa#FaHeart JavaScript Examples

The following examples show how to use react-icons/fa#FaHeart. 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: Footer.js    From weatherman-react with GNU General Public License v3.0 6 votes vote down vote up
Footer = () => {
  return (
    <div
      id="footer"
      className="p-4 d-flex flex-column flex-sm-column flex-md-row flex-lg-row justify-content-center align-items-center text-light w-100"
      style={{ backgroundColor: "rgb(33, 37, 41)" }}
    >
      <div className="footer-component text-center d-flex  w-100 w-md-25 my-2 my-md-0 justify-content-center">
        <a href="https://github.com/dsaw/weatherman-react">Github</a>
      </div>
      <div className="footer-component text-center d-flex  w-100 w-md-50 my-2 my-md-0 justify-content-center">
        Made with&nbsp;
        <span title="Heart" role="img" aria-label="Love">
          {" "}
          <FaHeart color={"#e31b23"} size={18} />{" "}
        </span>
        &nbsp;using&nbsp;
        <span title="React" role="img" aria-label="React">
          {" "}
          <FaReact color={"#2acef7"} size={18} />{" "}
        </span>
        &nbsp;by&nbsp; <a href="/"> Devesh</a>
      </div>
      <div className="footer-component text-center d-flex w-100 w-md-25 my-2 my-md-0 justify-content-center">
        <a href="https://github.com/dsaw/weatherman-react/blob/master/PRIVACY-POLICY.html">
          Privacy Policy{" "}
        </a>
      </div>
    </div>
  );
}
Example #2
Source File: MyPostsPage.jsx    From Socialgram with Apache License 2.0 6 votes vote down vote up
Post = ({ post }) => {
  return (
    <div key={post.id} className="container bg-dark mt-3 mb-3 p-3 post rounded">
      <h3 className="mb-3">{parse(post.title)}</h3>
      <div className="icon-container d-flex">
        <div className="icons" title="like">
          <FaThumbsUp className="pe-1" />
          <span>{post.likes}</span>
        </div>
        <div className="icons" title="dislike">
          <FaThumbsDown className="pe-1" />
          <span>{post.dislikes}</span>
        </div>
        <div className="icons hearts" title="heart">
          <FaHeart className="pe-1" />
          <span>{post.hearts}</span>
        </div>
      </div>

      {post.comments.map((comment) => (
        <div
          key={comment.id}
          className="container p-3 mb-2 shadow-lg rounded-lg"
        >
          {parse(comment.comments)}
        </div>
      ))}
    </div>
  );
}
Example #3
Source File: Footer.js    From ReactJS-Projects with MIT License 5 votes vote down vote up
Footer = () => {
  return (
    <footer className="bg-info text-center pt-3 pb-2 mt-5 sticky-bottom">
      Made with <FaHeart /> using React, 2022
    </footer>
  );
}
Example #4
Source File: index.js    From haskell.foundation with MIT License 5 votes vote down vote up
icons = {
  heart: <FaHeart />,
  lock: <FaLockOpen />,
  users: <FaUserFriends />,
  cubes: <FaCubes />,
  user: <FaUser />
}
Example #5
Source File: Player.jsx    From bottle-radio with MIT License 4 votes vote down vote up
Player = () => {
  const variables = window._env_ ? window._env_ : { REACT_ICECAST_URL: "" };
  const [playing, setPlaying] = useState(false);
  const [loading, setLoading] = useState(false);
  const [muted, setMuted] = useState(false);
  const [firstLoad, setFirstLoad] = useState(true);
  const [nowPlaying, setNowPlaying] = useState(["No data", "No data"]);
  const [listeners, setListeners] = useState([0, 0]);
  const { colorMode } = useColorMode();
  const colorHover = { light: "white", dark: "black" };
  const { isOpen, onOpen, onClose } = useDisclosure();
  const trackLinks = useSaveTrack(
    nowPlaying[0],
    nowPlaying[1]
  );
  const audioRef = useRef(null);
  const { setPlayer } = useContext(VisualiserContext);

  useEffect(() => {
    const audio = document.getElementById("player");
    if (audio) {
      setPlayer(audioRef);
    }
  }, [setPlayer]);

  useEffect(() => {
    const updateStats = async () => {
      let url = variables.REACT_ICECAST_URL + "status-json.xsl";
      let response = await fetch(url);
      let json = await response.json();
      let track = json.icestats.source.title;
      if (track && track !== "") {
        let artist = track.split(" - ")[0];
        track = track.split(" - ").slice(1).join(" - ");
        setNowPlaying([track, artist]);
      }
      let listeners = json.icestats.source.listeners;
      let peakListeners = json.icestats.source.listener_peak;

      if (listeners && listeners) {
        setListeners([listeners, peakListeners]);
      }
    };
    updateStats();
    setInterval(() => {
      updateStats();
    }, 10000);
  }, [variables.REACT_ICECAST_URL]);

  const togglePlay = () => {
    let player = document.getElementById("player");
    if (firstLoad) {
      setFirstLoad(false);
    }
    if (player.paused) {
      setPlaying(true);
      player.load();
      player.play();
    } else {
      setPlaying(false);
      player.pause();
    }
  };

  const changeVolume = (value) => {
    let player = document.getElementById("player");
    value <= 0 ? setMuted(true) : setMuted(false);
    player.volume = value / 100;
  };

  const TrackModal = (props) => {
    const { modal, setModal } = useContext(ModalContext);

    useEffect(() => {
      if (!modal) {
        setModal(trackLinks);
      }
    }, [modal, setModal]);

    return (
      <div>
        <Modal
          isOpen={isOpen}
          onClose={() => {
            onClose();
            setModal();
          }}
          size="sm"
          isCentered
        >
          <ModalOverlay>
            <ModalContent>
              <ModalCloseButton />
              <ModalBody>
                <Grid templateColumns="1fr 1fr" justifyItems="center" gap={0}>
                  {modal && modal.length > 0 ? (
                    modal.map((link) => (
                      <Link key={link.url} href={link.url} isExternal>
                        <Button variant="ghost">{link.displayName}</Button>
                      </Link>
                    ))
                  ) : (
                    <div>
                      <Spinner size="sm" /> Loading...
                    </div>
                  )}
                </Grid>
              </ModalBody>
            </ModalContent>
          </ModalOverlay>
        </Modal>
      </div>
    );
  };

  return (
    <div>
      <Flex
        direction="column"
        justify="center"
        align="center"
        width="100%"
        height="100%"
      >
        <Box>
          <Grid
            m={2}
            p={2}
            templateColumns="auto 1fr auto"
            alignItems="center"
            gap={1}
          >
            <Box
              gridRow="1/4"
              w="80px"
              h="80px"
              aria-label="Play toggle"
              as={loading ? FaSpinner : playing ? FaPauseCircle : FaPlayCircle}
              onClick={togglePlay}
              _hover={{ color: colorHover[colorMode] }}
              mr={1}
              className={loading ? "icon-spin" : ""}
            />
            <Text m={0} align="center">
              <strong>{nowPlaying[0]}</strong>
            </Text>
            <Text m={0} align="center">
              {nowPlaying[1]}
            </Text>

            <Flex direction="row" justify="center" maxWidth={400} p={2}>
              <Slider
                defaultValue={100}
                min={0}
                max={100}
                step={10}
                onChange={changeVolume}
                width="80px"
              >
                <SliderTrack>
                  <SliderFilledTrack bg="tomato" />
                </SliderTrack>
                <SliderThumb size={2} />
              </Slider>
              <Box
                w="20px"
                h="20px"
                as={muted ? FaVolumeMute : FaVolumeUp}
                ml={3}
              />
              <audio
                id="player"
                crossOrigin="anonymous"
                autoPlay
                preload="none"
                ref={audioRef}
                onPlay={() => setPlaying(true)}
                onPause={() => setPlaying(false)}
                onLoadStart={() => {
                  if (!firstLoad) {
                    setLoading(true);
                  }
                }}
                onCanPlay={() => setLoading(false)}
              >
                <source
                  src={variables.REACT_ICECAST_URL + "radio.mp3"}
                  type="audio/mp3"
                />
                Your browser does not support the audio element.
              </audio>
            </Flex>
            <Text gridColumn="1/4">
              <strong>Listeners: </strong>
              {listeners[0]} <strong>Peak: </strong>
              {listeners[1]}
            </Text>
            <Box gridColumn="3" gridRow="1/4" alignItems="center">
              <Box
                w="25px"
                h="25px"
                as={FaHeart}
                mx={1}
                onClick={onOpen}
                _hover={{ color: "tomato" }}
              />
              {isOpen ? <TrackModal /> : null}
            </Box>
          </Grid>
        </Box>
      </Flex>
    </div>
  );
}
Example #6
Source File: productItem.js    From next-ecommerce with MIT License 4 votes vote down vote up
export default function ProductSection({ id, name, rating, img_url, price }) {
  const cart = useQuery(CART);
  const wishlist = useQuery(WISHLIST);

  return (
    <article>
      <div className="top-buttons">
        <button className="add-wishlist" onClick={() => toggleWishlist(id)}>
          {wishlist.data.wishlist.products.includes(id) && (
            <FaHeart size={20} color="#D8D8D8" />
          )}
          {!wishlist.data.wishlist.products.includes(id) && (
            <FaRegHeart size={20} color="#D8D8D8" />
          )}
        </button>
      </div>

      <div className="product-img-box">
        <Link href={`/product/${id}`}>
          <img className="product-img" src={img_url} />
        </Link>
      </div>

      <Link href={`/product/${id}`}>
        <a className="product-name">{name}</a>
      </Link>

      <div className="rating">
        <StarRatings
          rating={parseFloat(rating)}
          starRatedColor="#F9AD3D"
          numberOfStars={5}
          name="rating"
          starDimension="20px"
          starSpacing="1px"
        />
      </div>

      <div className="price">
        <p className="price-value">${price}</p>
        <button className="add-cart" onClick={() => toggleCart(id)}>
          {cart.data.cart.products.includes(id) && (
            <FaCartArrowDown size={18} color="#D8D8D8" />
          )}
          {!cart.data.cart.products.includes(id) && (
            <FaCartPlus size={18} color="#D8D8D8" />
          )}
        </button>
      </div>

      <style jsx>{`
        article {
          display: flex;
          align-items: center;
          flex-direction: column;
          box-sizing: border-box;
          height: 100%;
          padding: 24px;
          background: white;
          box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.05);
          border-radius: 6px;
        }
        .top-buttons {
          margin-bottom: 24px;
          align-self: flex-end;
        }
        .top-buttons .add-wishlist {
          background: none;
          border: none;
        }
        .top-buttons .add-wishlist:focus {
          outline: none;
        }
        .product-img-box {
          margin-bottom: 28px;
        }
        .product-img {
          width: 225px;
          height: 160px;
          object-fit: contain;
        }
        .product-name {
          width: 80%;
          line-height: 20px;
          text-decoration: none;
          font-weight: 500;
          font-size: 14px;
          text-align: center;
          color: #666666;
          margin-bottom: 18px;
        }
        .product-name:hover {
          text-decoration: underline;
          font-weight: 600;
        }
        .rating {
          margin-bottom: 24px;
        }
        .price {
          display: flex;
          align-items: center;
          font-weight: 900;
          font-size: 16px;
          color: #666666;
        }
        .price .add-cart {
          background: none;
          border: none;
          margin-left: 5px;
        }
        .price .add-cart:focus {
          outline: none;
        }
      `}</style>
    </article>
  );
}
Example #7
Source File: [id].js    From next-ecommerce with MIT License 4 votes vote down vote up
export default function Home() {
  const router = useRouter();
  const { id } = router.query;
  const cart = useQuery(CART);
  const wishlist = useQuery(WISHLIST);

  const { data, loading, error } = useQuery(PRODUCTS_BY_IDS, {
    variables: {
      id,
    },
  });

  if ((error || !data?.productsById.length) && !loading) {
    return (
      <Page title="Quantum E-commerce - Products">
        <ErrorAlert message="This product is not found!"></ErrorAlert>
      </Page>
    );
  } else if (loading) {
    return (
      <Page title="Quantum E-commerce - Products">
        <p>Loading...</p>
      </Page>
    );
  }

  return (
    <Page title="Quantum E-commerce - Products">
      <article>
        <div className="top-buttons">
          <button
            className="add-wishlist"
            onClick={() => toggleWishlist(data.productsById[0].id)}
          >
            {wishlist.data.wishlist.products.includes(
              data.productsById[0].id
            ) && <FaHeart size={20} color="#D8D8D8" />}
            {!wishlist.data.wishlist.products.includes(
              data.productsById[0].id
            ) && <FaRegHeart size={20} color="#D8D8D8" />}
          </button>
        </div>

        <div className="product-img-box">
          <img className="product-img" src={data.productsById[0].img_url} />
        </div>

        <h1 className="product-name">{data.productsById[0].name}</h1>

        <h3 className="product-description">
          {data.productsById[0].description}
        </h3>

        <div className="rating">
          <StarRatings
            rating={parseFloat(data.productsById[0].rating)}
            starRatedColor="#F9AD3D"
            numberOfStars={5}
            name="rating"
            starDimension="20px"
            starSpacing="1px"
          />
        </div>

        <div className="price">
          <p className="price-value">${data.productsById[0].price}</p>
          <button
            className="add-cart"
            onClick={() => toggleCart(data.productsById[0].id)}
          >
            {cart.data.cart.products.includes(data.productsById[0].id) && (
              <FaCartArrowDown size={24} color="#D8D8D8" />
            )}
            {!cart.data.cart.products.includes(data.productsById[0].id) && (
              <FaCartPlus size={24} color="#D8D8D8" />
            )}
          </button>
        </div>

        <style jsx>{`
          article {
            display: flex;
            align-items: center;
            flex-direction: column;
            box-sizing: border-box;
            height: 100%;
            width: 100%;
            padding: 24px;
            background: white;
            box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.05);
            border-radius: 6px;
          }
          .top-buttons {
            margin-bottom: 24px;
            align-self: flex-end;
          }
          .top-buttons .add-wishlist {
            background: none;
            border: none;
          }
          .top-buttons .add-wishlist:focus {
            outline: none;
          }
          .product-img-box {
            margin-bottom: 28px;
          }
          .product-img {
            width: 320px;
            height: 230px;
            object-fit: contain;
          }
          .product-name {
            width: 80%;
            line-height: 20px;
            text-decoration: none;
            font-weight: 500;
            font-size: 22px;
            text-align: center;
            color: #666666;
            margin-bottom: 28px;
          }
          .product-description {
            width: 40%;
            line-height: 22px;
            text-decoration: none;
            font-weight: 400;
            font-size: 14px;
            text-align: center;
            color: #666666;
            margin-bottom: 24px;
          }
          .rating {
            margin-bottom: 18px;
          }
          .price {
            display: flex;
            align-items: center;
            font-weight: 900;
            font-size: 20px;
            color: #666666;
            margin-bottom: 20px;
          }
          .price .add-cart {
            background: none;
            border: none;
            margin-left: 5px;
          }
          .price .add-cart:focus {
            outline: none;
          }
          @media (max-width: 1000px) {
            .product-img {
              width: 225px;
              height: 180px;
              margin-bottom: 28px;
            }
            .product-name {
              width: 80%;
              line-height: 20px;
              text-decoration: none;
              font-weight: 500;
              font-size: 18px;
              text-align: center;
              color: #666666;
              margin-bottom: 18px;
            }
            .product-description {
              width: 80%;
              line-height: 22px;
              text-decoration: none;
              font-weight: 400;
              font-size: 14px;
              text-align: center;
              color: #666666;
              margin-bottom: 18px;
            }
          }
        `}</style>
      </article>
    </Page>
  );
}
Example #8
Source File: Footer.jsx    From nextjs-prismic-blog-starter with MIT License 4 votes vote down vote up
Footer = () => {
  return (
    <footer
      sx={{
        bg: 'muted',
      }}>
      <div className='footer'>
        {/* <div className="links-row">
          <div>
            <a
              href="https://github.com/iamsainikhil/nextjs-prismic-blog-starter"
              target="_blank"
              rel="noreferrer noopener"
              className="special-link"
              aria-label="GitHub"
              title="GitHub"
              sx={{ color: 'primary' }}
              onClick={() =>
                trackGAEvent(
                  'footer links',
                  `clicked on GitHub link in Footer`,
                  'link click'
                )
              }
            >
              GitHub
            </a>
          </div>
          <div>
            <a
              href="https://iamsainikhil.com/privacy-policy"
              target="_blank"
              rel="noreferrer noopener"
              className="special-link"
              aria-label="Privacy Policy"
              title="Privacy Policy"
              sx={{ color: 'primary' }}
              onClick={() =>
                trackGAEvent(
                  'footer links',
                  `clicked on Privacy Policy link in Footer`,
                  'link click'
                )
              }
            >
              Privacy Policy
            </a>
          </div>
        </div> */}

        <div
          style={{
            textAlign: 'center',
            margin: '0.25rem auto',
            wordSpacing: '0.2rem',
          }}>
          Made with{' '}
          <FaHeart
            style={{color: '#CC3D5C', marginBottom: '-0.25rem'}}
            aria-label='Love'
            title='Love'
          />{' '}
          using{' '}
          <SiNextDotJs
            sx={{
              color: 'text',
              marginBottom: '-0.25rem',
            }}
            aria-label='NextJS'
            title='NextJS'
          />{' '}
          and{' '}
          <picture className='prismic-icon'>
            <source type='image/webp' srcSet='/prismic-icon.webp' />
            <source type='image/jpeg' srcSet='/prismic-icon.jpg' />
            <img
              src='/prismic-icon.jpg'
              alt='Prismic'
              aria-label='Prismic'
              title='Prismic'
              className='prismic-icon'
            />
          </picture>
        </div>

        <div className='social-row'>
          {/* <Icon
            name="Facebook"
            url="https://facebook.com"
            style={{
              color: 'primary',
              fontSize: '1.75rem'
            }}
          /> */}

          <Icon
            name='Twitter'
            url='https://twitter.com/iamsainikhil12'
            style={{
              color: 'primary',
              fontSize: '1.5rem',
            }}
          />

          <Icon
            name='Medium'
            url='https://medium.com/@iamsainikhil'
            style={{
              color: 'primary',
              fontSize: '1.5rem',
            }}
          />

          <Icon
            name='LinkedIn'
            url='https://www.linkedin.com/in/iamsainikhil'
            style={{
              color: 'primary',
              fontSize: '1.70rem',
              marginBottom: '0.25rem',
            }}
          />
        </div>

        <p style={{textAlign: 'center', marginTop: '0.5rem'}}>
          © {new Date().getFullYear()}{' '}
          <a
            href='https://iamsainikhil.com'
            target='_blank'
            rel='noreferrer noopener'
            className='special-link'
            aria-label='Portfolio'
            title='Portfolio'
            sx={{color: 'primary'}}
            onClick={() =>
              trackGAEvent(
                'footer links',
                `clicked on copyright link in Footer`,
                'text click'
              )
            }>
            Sai&nbsp;Nikhil
          </a>
        </p>
      </div>
    </footer>
  )
}
Example #9
Source File: Post.jsx    From Socialgram with Apache License 2.0 4 votes vote down vote up
Post = ({
  post,
  addLikes,
  addComment,
  disLikes,
  hearts,
  commentText,
  setCommentText,
}) => {
  const [user, setUser] = useState("");

  useEffect(() => {
    const ac = new AbortController();
    const fetchIds = async () => {
      try {
        apiPlain.getSingle(`userId`, ac.signal, "").then((res) => {
          if (!Array.isArray(res)) {
            return;
          }
          const userData = res?.filter((ids) => ids._id === post.userId);
          if (userData?.length) {
            setUser(userData[0]?.fname);
          } else {
            setUser("Deleted User");
          }
        });
      } catch (error) {
        console.log(error);
      }
    };
    fetchIds();
    return () => ac.abort();
  }, [post._id, post.userId, post]);

  return (
    <React.Fragment>
      <div
        key={post.id}
        className="container bg-dark mt-3 mb-3 p-3 post rounded"
      >
        <h3 className="mb-3">{parse(post.title)}</h3>
        <div className="my-4 d-flex justify-content-between">
          <p className="text-muted">Posted By: {user}</p>
          <p className="text-muted">
            {post.date ? convertDate(post.date) : "Just now"}
          </p>
        </div>
        <div className="icon-container d-flex">
          <div
            className="icons"
            title="like"
            onClick={() => addLikes(post.id, post.likes)}
          >
            <FaThumbsUp className="pe-1" />
            <span>{post.likes}</span>
          </div>
          <div
            className="icons"
            title="dislike"
            onClick={() => disLikes(post.id, post.dislikes)}
          >
            <FaThumbsDown className="pe-1" />
            <span>{post.dislikes}</span>
          </div>
          <div
            className="icons hearts"
            title="heart"
            onClick={() => hearts(post.id, post.hearts)}
          >
            <FaHeart className="pe-1" />
            <span>{post.hearts}</span>
          </div>
        </div>
        <div className="input-group mb-3 mt-3">
          <form className="w-100">
            <div className="form-group w-100">
              <input
                type="text"
                className="form-control w-100"
                placeholder="comment"
                value={commentText}
                onChange={(event) => setCommentText(event.target.value)}
                required
              />
            </div>
            <div className="button-container text-center mt-3 mb-3">
              <button
                style={{ width: "100%" }}
                className="btn btn-primary"
                onClick={(event) => {
                  event.preventDefault();
                  addComment(post.id, post.comments);
                }}
              >
                Add Comment
              </button>
            </div>
          </form>
        </div>
        <div
          style={{ maxHeight: "20vh", overflowY: "auto" }}
          className="d-flex flex-column-reverse"
        >
          {post.comments.map((comment) => (
            <div
              key={comment.id}
              className="container p-3 mb-2 shadow-lg rounded-lg w-100"
            >
              {parse(comment.comments)}
            </div>
          ))}
        </div>
      </div>
    </React.Fragment>
  );
}
Example #10
Source File: Board.js    From ytx-card-game with MIT License 4 votes vote down vote up
Board = (props) => {
	const { state, dispatch } = useContext(store)
	const isGamePaused = () => state.game && state.game.gamePaused
	const [allyCards, setAllyCards] = useState({
		[ALLY_TYPES.hand]: [],
		[ALLY_TYPES.field]: [],
	})

	useLayoutEffect(() => {
		if (state.game) {
			if (state.playerNumber === 1) {
				setAllyCards({
					[ALLY_TYPES.hand]: [...state.game.player1.hand],
					[ALLY_TYPES.field]: [...state.game.player1.field],
				})
			} else {
				setAllyCards({
					[ALLY_TYPES.hand]: [...state.game.player2.hand],
					[ALLY_TYPES.field]: [...state.game.player2.field],
				})
			}
		}
	}, [state.game])

	const getAllyStateType = (droppableId) => {
		return allyCards[droppableId]
	}

	const invokeCard = (card) => {
		console.log('invoke card', card)
		if (!card.isInvoked) {
			let me
			if (state.playerNumber === 1) {
				me = state.game.player1
			} else {
				me = state.game.player2
			}
			// Invokes a card into the field and updates ally hand with a new deep copy
			if (me.field.length >= FIELD_SIZE) {
				return dispatch({
					type: 'SET_ERROR',
					payload: {
						error: 'The field is full',
					},
				})
			}
			if (card.cost > me.energy) {
				return dispatch({
					type: 'SET_ERROR',
					payload: {
						error:
							"You don't have enough energy to invoke this card",
					},
				})
			}
			card.isInvoked = true
			state.socket.emit('invoke-card', {
				game: state.game,
				card,
			})
		}
	}

	const onDragEnd = useCallback(
		(result) => {
			const { source, destination } = result
			if (!destination) {
				return
			}
			let allyState = getAllyStateType(source.droppableId)
			const isEnoughEnergyToInvoke =
				state.playerNumber === 1
					? state.game.player1.energy
					: state.game.player2.energy
			console.log(
				isEnoughEnergyToInvoke,
				allyState.cost,
				'energy',
				state.playerNumber,
				state.game.player1.energy,
				state.game.player2.energy,
			)
			if (isEnoughEnergyToInvoke < allyState[source.index].cost) {
				return
			}
			if (source.droppableId === destination.droppableId) {
				const items = reorder(
					allyState,
					source.index,
					destination.index,
				)
				setAllyCards({ ...allyCards, [source.droppableId]: items })
			} else {
				//invoke card
				invokeCard(allyCards[ALLY_TYPES.hand][source.index])
				const result = move(
					getAllyStateType(source.droppableId),
					getAllyStateType(destination.droppableId),
					source,
					destination,
				)
				setAllyCards({
					[ALLY_TYPES.hand]: result[ALLY_TYPES.hand],
					[ALLY_TYPES.field]: result[ALLY_TYPES.field],
				})
			}
		},
		[state.game, allyCards],
	)

	return (
		<Page>
			<ResultMsg
				winner={state.gameOver && state.areYouTheWinner}
				loser={state.gameOver && !state.areYouTheWinner}
			>
				{state.gameOver && state.areYouTheWinner
					? 'Congratulations! You are the winner!'
					: state.gameOver && !state.areYouTheWinner
						? 'You lost! Better luck next time!'
						: null}
			</ResultMsg>
			{/* <p>Turn: {state.game ? state.game.currentTurnNumber : 0}</p>
			<p>Timer: {props.turnCountdownTimer}</p> */}
			<ExitLink hidden={!state.gameOver} to="/">
				Exit
			</ExitLink>
			{state.game ? (
				<Game className="game">
					<EnemyDeck>Enemy's <br /> Deck</EnemyDeck>
					<YourDeck>Your <br /> Deck</YourDeck>
					<EnemyStatsBox
						className={
							state.isAttackMode
								? 'enemy-stats attack-mode'
								: 'enemy-stats'
						}
						onClick={() => {
							if (state.isAttackMode) props.attackDirectly()
						}}
					>
						<p>Enemy</p>
						<p>
							{state.playerNumber === 1
								? state.game.player2.life
								: state.game.player1.life}
							<FaHeart />
						</p>
						<p>
							{state.playerNumber === 1
								? state.game.player2.energy
								: state.game.player1.energy}
							<FaBolt />
						</p>
					</EnemyStatsBox>
					<AllyStatsBox className="my-stats">
						<p>You</p>
						<p>
							{state.playerNumber === 1
								? state.game.player1.life
								: state.game.player2.life}
							<FaHeart />
						</p>
						<p>
							{state.playerNumber === 1
								? state.game.player1.energy
								: state.game.player2.energy}
							<FaBolt />
						</p>
					</AllyStatsBox>
					<CardContainer className="cards-container enemy-cards-container">
						{state.visualEnemyHand}
					</CardContainer>
					<Field className="field">
						<DragDropContext onDragEnd={onDragEnd}>
							<EnemyField
								className={
									state.isAttackMode
										? 'enemy-field attack-mode'
										: 'enemy-field'
								}
							>
								{state.enemyFieldHtml}
							</EnemyField>
							<FieldContainer top >
								<Droppable
									droppableId={`${ALLY_TYPES.field}`}
									direction="horizontal"
								>
									{(provided, snapshot) => (
										<CardPanel
											ref={provided.innerRef}
											isDraggingOver={snapshot.isDraggingOver}
										>
											{allyCards[ALLY_TYPES.field].map(
												(allyFieldCard, index) => (
													<Draggable
														key={index}
														draggableId={`allyFieldCard${index}`}
														index={index}
														isDragDisabled={true}
													>
														{(
															provided,
															snapshot,
														) => (
															<div
																ref={
																	provided.innerRef
																}
																{...provided.draggableProps}
																{...provided.dragHandleProps}
															>
																<BoardCard
																	{...allyFieldCard}
																/>
															</div>
														)}
													</Draggable>
												),
											)}
											{provided.placeholder}
										</CardPanel>
									)}
								</Droppable>
							</FieldContainer>
							<FieldContainer bottom>
								<Droppable
									droppableId={`${ALLY_TYPES.hand}`}
									direction="horizontal"
								>
									{(provided, snapshot) => (
										<CardPanel
											ref={provided.innerRef}
											// isDraggingOver={snapshot.isDraggingOver}
											outter
										>
											{allyCards[ALLY_TYPES.hand].map(
												(allyHandCard, index) => (
													<Draggable
														key={index}
														draggableId={`allyHand${index}`}
														index={index}
														isDragDisabled={
															state.playerNumber !==
															state.game
																.currentPlayerTurn
														}
													>
														{(
															provided,
															snapshot,
														) => (
															<div
																ref={
																	provided.innerRef
																}
																{...provided.draggableProps}
																{...provided.dragHandleProps}
															>
																<BoardCard
																	{...allyHandCard}
																/>
															</div>
														)}
													</Draggable>
												),
											)}
											{provided.placeholder}
										</CardPanel>
									)}
								</Droppable>
							</FieldContainer>
						</DragDropContext>
					</Field>
					<Button
						className="end-turn"
						disabled={state.isOtherPlayerTurn || isGamePaused()}
						onClick={() => {
							props.endTurn()
						}}
					>
						End Turn
					</Button>
					<Button
						className="surrender"
						style={{
							backgroundColor: 'red',
						}}
						disabled={isGamePaused()}
						onClick={() => {
							props.surrender()
						}}
					>
						Surrender
					</Button>
				</Game>
			) : (
					<p>Game loading...</p>
				)}
		</Page>
	)
}
Example #11
Source File: BoardCard.js    From ytx-card-game with MIT License 4 votes vote down vote up
BoardCard = (props) => {
	const card_names = {
		one,
		two,
		three,
		four,
		five,
		six,
		seven,
		eight,
		nine,
		ten,
		eleven,
		twelve,
		tt,
		zz
	}

	let img_name;

	if (Object.keys(card_names).includes(props.card_img)) {
		img_name = card_names[props.card_img]
	}

	const { state, dispatch } = useContext(store)

	const toggleAttackMode = (cardId) => {
		let isAttackMode = cardId == 0 ? false : !state.isAttackMode
		dispatch({
			type: 'SET_ATTACK_MODE',
			payload: {
				isAttackMode,
				attackingCardId: cardId,
			},
		})
	}

	/**
	 * @dev Burns the selected card on hand and refund a part of the cost as energy to the player
	 * @param {String} cardID
	 */
	const burnCardOnHand = (cardID) => {
		state.socket.emit('burn-card', {
			currentGameID: state.game.gameId,
			cardID,
			burnType: 'hand',
		})
	}

	const isGamePaused = () => state.game && state.game.gamePaused
	let isAllyCard = state.playerNumber === props.playerNumberOwner
	// If the card is ally, display the attack button or invoke, else don't display actions
	let buttonToDisplay
	if (props.isInvoked && isAllyCard) {
		buttonToDisplay = (
			<CardButton
				disabled={
					!props.canAttack ||
					state.isOtherPlayerTurn ||
					isGamePaused()
				}
				onClick={() => {
					toggleAttackMode(props.id)
				}}
			>
				Attack
			</CardButton>
		)
	} else if (isAllyCard) {
		buttonToDisplay = (
			<div>
				<CardButton
					style={{
						backgroundColor: '#ffad04',
					}}
					disabled={state.isOtherPlayerTurn || isGamePaused()}
					onClick={() => {
						burnCardOnHand(props.id)
					}}
				>
					Burn
				</CardButton>
			</div>
		)
	}

	const renderSwitch = (param) => {
		switch (param) {
			case 'wind':
				return <FiWind />;
			case 'fire':
				return <ImFire />;
			case 'water':
				return <GiDrop />;
			case 'death':
				return <GiDeathSkull />;
			case 'life':
				return <FaHeart />;
			case 'neutral':
				return <FiMinusCircle />;
			default:
				return param;
		}
	}
	return (
		<StyledCard data-id={props.dataId} card_name={img_name}>
			<div>{props.cost}<FaBolt size={18} /> </div>
			<div><span>{props.life}</span><FaHeart color={'rgba(255, 255, 255, 0.3)'} size={26} /> </div>
			<div><span>{props.attack}</span><GiBowieKnife color={'rgba(255, 255, 255, 0.3)'} size={26} /> </div>
			<div className={'card ' + props.type}>{renderSwitch(props.type)}</div>
			<div className="spacer"></div>
			{buttonToDisplay}
		</StyledCard>
	)
}