@apollo/client#isApolloError TypeScript Examples

The following examples show how to use @apollo/client#isApolloError. 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: LoginView.tsx    From storefront with MIT License 4 votes vote down vote up
LoginView: React.VFC = () => {
  const [alert, setAlert] = useState<string>();
  const { closeModal } = useUI();
  const [login, { loading }] = useLoginMutation();

  const { control, formState, handleSubmit } = useForm<LoginMutationVariables>({
    resolver: yupResolver(validationSchema),
  });

  const onSubmit = handleSubmit(async (variables) => {
    try {
      const { data } = await login({ variables });

      if (data?.login?.authToken != null) {
        localStorage.setItem('authToken', data.login.authToken);
      }
      if (data?.login?.refreshToken != null) {
        localStorage.setItem('refreshToken', data.login.refreshToken);
      }
      closeModal();
    } catch (error) {
      if (isApolloError(error)) {
        setAlert(error.graphQLErrors[0].message);
      }
    }
  });

  return (
    <>
      <Box sx={{ textAlign: 'center', mb: 6 }}>
        <Logo />
      </Box>
      <form onSubmit={onSubmit}>
        {alert && (
          <Box sx={{ mb: 2 }}>
            <Alert severity="error">{alert}</Alert>
          </Box>
        )}
        {/* Username or email */}
        <Controller
          control={control}
          name="username"
          render={({ field }) => (
            <TextField
              required
              autoCapitalize="off"
              autoCorrect="off"
              error={'username' in formState.errors}
              helperText={formState.errors.username?.message}
              label="Username or email"
              type="text"
              {...field}
            />
          )}
        />
        {/* Password */}
        <Controller
          control={control}
          name="password"
          render={({ field }) => (
            <TextField
              required
              error={'password' in formState.errors}
              helperText={formState.errors.password?.message}
              label="Password"
              type="password"
              {...field}
            />
          )}
        />
        <Box sx={{ mt: 1 }}>
          <Button fullWidth type="submit" color="primary" loading={loading}>
            Log in
          </Button>
        </Box>
        <Box sx={{ mt: 1, textAlign: 'center' }}>
          Don’t have an account? <Link href="/register">Register</Link>
        </Box>
      </form>
    </>
  );
}
Example #2
Source File: ContactForm.tsx    From storefront with MIT License 4 votes vote down vote up
ContactForm: React.VFC = () => {
  const { addAlert } = useUI();
  const [shouldSend, setShouldSend] = useState(true);

  const [contact, { loading }] = useContactMutation();

  const { control, formState, handleSubmit, reset } = useForm<ContactFormData>({
    defaultValues: {
      acceptance: false,
      email: '',
      name: '',
      message: '',
      phone: '',
      subject: '',
    },
    mode: 'onChange',
    resolver: yupResolver(validationSchema),
  });

  const onSubmit = handleSubmit(async (values) => {
    if (shouldSend) {
      try {
        const { data } = await contact({ variables: values });
        if (data?.contact?.message != null) {
          addAlert(data.contact.message);
          reset();
        }
      } catch (error) {
        if (isApolloError(error)) {
          addAlert(error.message, { severity: 'error' });
        }
      }
    }
  });

  return (
    <form onSubmit={onSubmit}>
      <Grid container spacing={2}>
        <Grid item xs={6}>
          {/* Name */}
          <Controller
            control={control}
            name="name"
            render={({ field }) => (
              <TextField
                required
                error={'name' in formState.errors}
                helperText={formState.errors.name?.message}
                label="Name"
                type="text"
                {...field}
              />
            )}
          />
        </Grid>
        <Grid item xs={6}>
          {/* Email */}
          <Controller
            control={control}
            name="email"
            render={({ field }) => (
              <TextField
                required
                error={'email' in formState.errors}
                helperText={formState.errors.email?.message}
                label="Email"
                type="email"
                {...field}
              />
            )}
          />
        </Grid>
      </Grid>
      <Grid container spacing={2}>
        <Grid item xs={6}>
          {/* Phone */}
          <Controller
            control={control}
            name="phone"
            render={({ field }) => (
              <TextField
                error={'phone' in formState.errors}
                helperText={formState.errors.phone?.message}
                label="Phone"
                type="text"
                {...field}
              />
            )}
          />
        </Grid>
        <Grid item xs={6}>
          {/* Subject */}
          <Controller
            control={control}
            name="subject"
            render={({ field }) => (
              <TextField
                error={'subject' in formState.errors}
                helperText={formState.errors.subject?.message}
                label="Subject"
                type="text"
                {...field}
              />
            )}
          />
        </Grid>
      </Grid>
      {/* Message */}
      <Controller
        control={control}
        name="message"
        render={({ field }) => (
          <TextField
            multiline
            required
            error={'message' in formState.errors}
            helperText={formState.errors.message?.message}
            label="Message"
            rows={6}
            {...field}
          />
        )}
      />
      {/* Acceptance */}
      <FormGroup>
        <FormControlLabel
          control={
            <Controller
              control={control}
              name="acceptance"
              render={({ field }) => (
                <Checkbox
                  checked={field.value}
                  inputRef={field.ref}
                  name={field.name}
                  onBlur={() => field.onBlur()}
                  onChange={(e) => field.onChange(e.target.checked)}
                />
              )}
            />
          }
          label="I agree that my submitted data is being collected and stored."
        />
      </FormGroup>
      {/* Acceptance */}
      <FormGroup>
        <FormControlLabel
          control={<Checkbox onChange={(e) => setShouldSend(!e.target.checked)} />}
          label="If you are a spambot, you should check this."
        />
      </FormGroup>
      <Button type="submit" color="primary" disabled={!formState.isValid} loading={loading}>
        Submit
      </Button>
    </form>
  );
}
Example #3
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 #4
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>
  );
}
Example #5
Source File: register.tsx    From storefront with MIT License 4 votes vote down vote up
Register: NextPage = () => {
  const [successMessage, setSuccessMessage] = useState<string>();
  const router = useRouter();
  const [registerUser, { loading }] = useRegisterMutation();
  const { addAlert } = useUI();

  /** Hide the Status bar on cross button click. */
  const handleCloseButtonClick = () => {
    // Remove the message.
    setSuccessMessage(undefined);
  };

  /**
   * Handle registration success.
   *
   * @param data Result data received
   */
  const handleRegisterUserSuccess = (data: RegisterMutation) => {
    if (data.registerUser?.user?.email != null) {
      // Add a message.
      setSuccessMessage('Registration Successful! You will be redirected to login page now...');

      setTimeout(() => {
        // Send the user to Login page.
        router.push('/login?registered=true');
      }, 3000);
    }
  };

  const { control, formState, handleSubmit } = useForm<RegisterFormData>({
    resolver: yupResolver(validationSchema),
  });

  const onSubmit = handleSubmit(async ({ email, password, username }) => {
    try {
      const { data } = await registerUser({
        variables: { email, password, username },
      });
      if (data != null) {
        handleRegisterUserSuccess(data);
      }
    } catch (error) {
      if (isApolloError(error)) {
        addAlert(error.graphQLErrors[0].message, { severity: 'error' });
      }
    }
  });

  return (
    <Layout>
      <Container maxWidth="sm">
        <Box sx={{ mt: 6, pt: 6 }}>
          <Typography gutterBottom variant="h2">
            Register
          </Typography>
          {/* Success Message */}
          {successMessage != null && (
            <Alert severity="success" onClose={handleCloseButtonClick}>
              {successMessage}
            </Alert>
          )}
          <form onSubmit={onSubmit}>
            {/* Username */}
            <Controller
              control={control}
              name="username"
              render={({ field }) => (
                <TextField
                  required
                  autoComplete="username"
                  error={'username' in formState.errors}
                  helperText={formState.errors.username?.message}
                  label="Username"
                  type="text"
                  {...field}
                />
              )}
            />
            {/* Email */}
            <Controller
              control={control}
              name="email"
              render={({ field }) => (
                <TextField
                  required
                  autoComplete="email"
                  error={'email' in formState.errors}
                  helperText={formState.errors.email?.message}
                  label="Email"
                  type="email"
                  {...field}
                />
              )}
            />
            {/* Password */}
            <Controller
              control={control}
              name="password"
              render={({ field }) => (
                <TextField
                  required
                  autoComplete="new-password"
                  error={'password' in formState.errors}
                  helperText={formState.errors.password?.message}
                  label="Password"
                  type="password"
                  {...field}
                />
              )}
            />
            <Box sx={{ mt: 2 }}>
              <Button type="submit" color="primary" loading={loading}>
                Register
              </Button>
            </Box>
          </form>
        </Box>
      </Container>
    </Layout>
  );
}