@material-ui/core#Stack TypeScript Examples

The following examples show how to use @material-ui/core#Stack. 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: ProductGrid.tsx    From storefront with MIT License 5 votes vote down vote up
ProductGrid: React.VFC<Props> = ({ loading, products }) => {
  if (!loading && products.length === 0) {
    return <Typography>No products found.</Typography>;
  }

  return (
    <Grid container spacing={4}>
      {loading
        ? rangeMap(12, (i) => (
            <Grid key={i} item xs={6} md={3}>
              <Skeleton variant="rectangular" height={375} />
            </Grid>
          ))
        : products.map(
            (product) =>
              product != null && (
                <Grid key={product.id} item xs={6} md={3}>
                  <Paper sx={{ height: '100%', textAlign: 'center' }}>
                    <Link
                      href={`/product/${product.slug}`}
                      underline="none"
                      sx={{ display: 'flex', flexDirection: 'column', height: '100%' }}
                    >
                      <Image height={673} loading="lazy" mediaItem={product.image} width={538} />
                      <Box sx={{ p: 2 }}>
                        {product.__typename === 'VariableProduct' && (
                          <Stack
                            direction="row"
                            spacing={1}
                            sx={{ justifyContent: 'center', mb: 2 }}
                          >
                            {product.paColors?.nodes?.map(
                              (color) =>
                                color?.name != null && (
                                  <ColorSwatch key={color.id} color={color.name} size="small" />
                                ),
                            )}
                          </Stack>
                        )}
                        <Typography gutterBottom variant="h4">
                          {product.name}
                        </Typography>
                        {(product.__typename === 'SimpleProduct' ||
                          product.__typename === 'VariableProduct') &&
                          (product.stockStatus === StockStatusEnum.OUT_OF_STOCK ? (
                            <Typography color="error" variant="h5">
                              Out of stock
                            </Typography>
                          ) : (
                            <Price color="primary" variant="h5">
                              {product.price}
                            </Price>
                          ))}
                        {product.__typename === 'ExternalProduct' && (
                          <Price color="primary" variant="h5">
                            {product.price}
                          </Price>
                        )}
                      </Box>
                    </Link>
                  </Paper>
                </Grid>
              ),
          )}
    </Grid>
  );
}
Example #2
Source File: VariationForm.tsx    From storefront with MIT License 5 votes vote down vote up
VariationForm: React.VFC<Props> = ({ onChange, product }) => {
  const variations = getVariations(product);

  const [formState, setFormState] = useSetState<Record<string, string | undefined>>(
    mapValues(variations, () => undefined),
  );

  useEffect(() => {
    const variation = product.variations?.nodes?.find((variation) =>
      variation?.attributes?.nodes?.every(
        (attribute) => attribute?.name != null && attribute.value === formState[attribute.name],
      ),
    );
    onChange(variation ?? undefined);
  }, [formState, onChange, product]);

  return (
    <div>
      {Object.entries(variations).map(([name, attribute]) => (
        <Box key={name} sx={{ my: 2 }}>
          <Typography gutterBottom variant="h4">
            {startCase(name.replace(/^pa_/, ''))}
          </Typography>
          <Stack direction="row" spacing={1}>
            {attribute.options.map((option) =>
              name === 'pa_color' ? (
                <ColorSwatch
                  key={option}
                  color={option}
                  selected={option === formState[name]}
                  onClick={() => {
                    setFormState({ [name]: option });
                  }}
                />
              ) : (
                <Button
                  key={option}
                  circle
                  color={option === formState[name] ? 'primary' : 'secondary'}
                  variant={option === formState[name] ? 'contained' : 'outlined'}
                  onClick={() => {
                    setFormState({ [name]: option });
                  }}
                >
                  {option}
                </Button>
              ),
            )}
          </Stack>
        </Box>
      ))}
    </div>
  );
}
Example #3
Source File: Footer.tsx    From storefront with MIT License 4 votes vote down vote up
Footer: React.VFC = () => {
  const { data: menu } = useMenuQuery({
    variables: { location: MenuLocationEnum.FOOTER_NAVIGATION },
  });

  return (
    <Box component="footer" sx={{ bgcolor: 'common.black' }}>
      <Container sx={{ overflow: 'hidden' }}>
        <Grid container spacing={4} sx={{ my: 6 }}>
          <Grid item xs={12} md={2}>
            <Logo />
          </Grid>
          {menu?.menuItems?.nodes?.map(
            (menuItem) =>
              menuItem != null &&
              (menuItem.childItems?.nodes?.length ?? 0) > 0 && (
                <Grid key={menuItem.id} item xs={12} md={2}>
                  <Typography variant="h4">{menuItem.label}</Typography>
                  <Box component="ul" sx={{ listStyle: 'none', p: 0, my: 2 }}>
                    {menuItem.childItems?.nodes?.map(
                      (childItem) =>
                        childItem != null && (
                          <Box key={childItem.id} component="li" sx={{ mb: 2 }}>
                            <Link href={relativeURL(childItem.url ?? '/')} variant="body1">
                              <span
                                // eslint-disable-next-line react/no-danger
                                dangerouslySetInnerHTML={{ __html: childItem.label ?? '' }}
                              />
                            </Link>
                          </Box>
                        ),
                    )}
                  </Box>
                </Grid>
              ),
          )}
          <Grid item xs={12} md={6} sx={{ ml: 'auto' }}>
            <Stack
              direction="row"
              justifyContent={{ xs: 'flex-start', md: 'flex-end' }}
              spacing={{ xs: 1, md: 3 }}
            >
              <IconButton
                href="https://www.facebook.com/artwithaliens"
                target="_blank"
                rel="noopener noreferrer"
                color="inherit"
                aria-label="Facebook"
              >
                <Facebook fontSize="large" />
              </IconButton>
              <IconButton
                href="https://www.instagram.com/artwithaliens/"
                target="_blank"
                rel="noopener noreferrer"
                color="inherit"
                aria-label="Instagram"
              >
                <Instagram fontSize="large" />
              </IconButton>
              <IconButton
                href="https://github.com/artwithaliens"
                target="_blank"
                rel="noopener noreferrer"
                color="inherit"
                aria-label="GitHub"
              >
                <Github fontSize="large" />
              </IconButton>
            </Stack>
          </Grid>
        </Grid>
        <Box sx={{ my: 6 }}>
          <Typography align="center">
            Copyright © 2018-{new Date().getFullYear()}{' '}
            <Link href="https://artwithaliens.com" target="_blank" rel="noopener noreferrer">
              Art With Aliens
            </Link>
          </Typography>
        </Box>
      </Container>
    </Box>
  );
}
Example #4
Source File: AddToCart.tsx    From storefront with MIT License 4 votes vote down vote up
AddToCart: React.VFC<Props> = ({ product }) => {
  const { addAlert } = useUI();

  const [showViewCart, setShowViewCart] = useState(false);
  const [variationId, setVariationId] = useState<number>();

  const [addToCart, { loading }] = useAddToCartMutation({
    refetchQueries: ['Cart'],
    awaitRefetchQueries: true,
  });

  /** Handles adding items to the cart. */
  const handleAddToCartClick = async () => {
    try {
      await addToCart({
        variables: {
          productId: product.databaseId,
          variationId,
        },
      });
      // Show View Cart Button
      setShowViewCart(true);
    } catch (error) {
      if (isApolloError(error)) {
        addAlert(error.message, { severity: 'error' });
      }
    }
  };

  /** Handles changing the variation. */
  const handleVariationChange = (variation?: PartialDeep<ProductVariation>) => {
    setVariationId(variation?.databaseId);
  };

  const viewCart = showViewCart && (
    <Button color="secondary" href="/cart">
      View cart
    </Button>
  );

  return product.__typename === 'ExternalProduct' ? (
    <Button
      color="primary"
      variant="contained"
      href={product.externalUrl ?? '/'}
      target="_blank"
      rel="noopener noreferrer"
    >
      Buy now
    </Button>
  ) : product.__typename === 'SimpleProduct' ? (
    <>
      <Stock product={product} />
      <Stack direction="row" spacing={1}>
        <Button
          color="primary"
          variant="contained"
          disabled={product.stockStatus === StockStatusEnum.OUT_OF_STOCK}
          loading={loading}
          onClick={handleAddToCartClick}
        >
          Add to cart
        </Button>
        {viewCart}
      </Stack>
    </>
  ) : product.__typename === 'VariableProduct' ? (
    <>
      <VariationForm product={product} onChange={handleVariationChange} />
      <Box sx={{ mt: 1 }}>
        <Stock
          product={product}
          variation={product.variations?.nodes?.find(
            (variation) => variation?.databaseId === variationId,
          )}
        />
      </Box>
      <Stack direction="row" spacing={1}>
        <Button
          color="primary"
          disabled={!variationId}
          loading={loading}
          size="large"
          variant="contained"
          onClick={handleAddToCartClick}
        >
          Add to cart
        </Button>
        {viewCart}
      </Stack>
    </>
  ) : null;
}
Example #5
Source File: cart.tsx    From storefront with MIT License 4 votes vote down vote up
Cart: NextPage = () => {
  const { addAlert } = useUI();
  const [coupon, setCoupon] = useState<string>();

  const { data: { cart } = { cart: undefined }, loading } = useCartQuery({
    fetchPolicy: 'no-cache',
    ssr: false,
  });

  const [updateCart, { loading: updating }] = useUpdateCartMutation({
    refetchQueries: ['Cart'],
    awaitRefetchQueries: true,
  });

  const [addCoupon, { loading: addingCoupon }] = useAddCouponMutation({
    refetchQueries: ['Cart'],
  });
  const [removeCoupon, { loading: removingCoupon }] = useRemoveCouponMutation({
    refetchQueries: ['Cart'],
  });

  /** Handles adding coupons to the cart. */
  const handleAddCouponClick = async () => {
    if (!isBlank(coupon)) {
      try {
        await addCoupon({ variables: { code: coupon } });
      } catch (error) {
        if (isApolloError(error)) {
          addAlert(error.message, { severity: 'error' });
        }
      }
    }
  };

  const handleCouponDelete = async (code: string) => {
    removeCoupon({ variables: { code } });
  };

  return (
    <Layout>
      <Container>
        <Box sx={{ mb: 2, mt: 6 }}>
          <Typography variant="h1">Cart</Typography>
        </Box>
        {loading ? (
          <Loader />
        ) : cart == null || (cart?.contents?.itemCount ?? 0) === 0 ? (
          <CartEmpty />
        ) : (
          <>
            <CartTable
              cart={cart}
              loading={updating || addingCoupon || removingCoupon}
              onUpdate={(values) => updateCart({ variables: values })}
            />
            <Grid container justifyContent="space-between">
              <Grid item xs={12} sm={4} sx={{ order: { xs: 2, sm: 1 } }}>
                <Box sx={{ mb: 4, mt: { xs: 0, sm: 4 } }}>
                  <Typography gutterBottom variant="h4">
                    I have a coupon
                  </Typography>
                  <Stack direction="row" spacing={1}>
                    <TextField
                      margin="none"
                      placeholder="Enter coupon code"
                      onChange={(event) => setCoupon(event.currentTarget.value)}
                    />
                    <Button
                      disabled={isBlank(coupon)}
                      loading={addingCoupon}
                      variant="contained"
                      onClick={handleAddCouponClick}
                    >
                      Add&nbsp;coupon
                    </Button>
                  </Stack>
                  <Box sx={{ mt: 2 }}>
                    {cart.appliedCoupons?.map(
                      (coupon) =>
                        coupon != null && (
                          <Chip
                            key={coupon.code}
                            color="secondary"
                            label={`Coupon "${coupon.code.toUpperCase()}"`}
                            onDelete={() => handleCouponDelete(coupon.code)}
                          />
                        ),
                    )}
                  </Box>
                </Box>
              </Grid>
              <Grid item xs={12} sm={4} sx={{ order: { xs: 1, sm: 2 } }}>
                <Box sx={{ my: 4 }}>
                  <Button fullWidth color="primary" href="/checkout/billing-address">
                    Proceed to Checkout
                  </Button>
                </Box>
              </Grid>
            </Grid>
          </>
        )}
      </Container>
    </Layout>
  );
}