-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cbc6763
commit 080521a
Showing
13 changed files
with
928 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Storefront UI Development | ||
## Build an account management page | ||
|
||
### Index | ||
This article is part of the [Storefront UI Development Guide](./storefront-intro.md). | ||
- Previous Task: [Add ability to log in](./storefront-login.md) | ||
- Next Task: [Show inventory status badges](./storefront-inventory-status-badges.md) | ||
|
||
### Overview | ||
After you've added the ability to log in, most storefronts also need an account management page, or multiple pages. Here your shoppers with accounts can update their profile information, their stored addresses, and their stored payment details, as well as view, track, and cancel their orders. | ||
|
||
Here is a list of GraphQL queries you'll likely need: | ||
- `viewer` | ||
- `ordersByAccountId` | ||
|
||
And mutations: | ||
- `addAccountAddressBookEntry` | ||
- `updateAccountAddressBookEntry` | ||
- `removeAccountAddressBookEntry` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# Storefront UI Development | ||
## Add a way to add an item to a cart | ||
|
||
### Index | ||
This article is part of the [Storefront UI Development Guide](./storefront-intro.md). | ||
- Previous Task: [Build navigation menus](./storefront-nav-menus.md) | ||
- Next Task: [Build a cart page](./storefront-cart-page.md) | ||
|
||
### Overview | ||
In Reaction, there are anonymous carts and account carts. For more information, refer to [Concepts: Carts](../developers-guide/concepts/carts.md). Since we haven't added a way to log in to the storefront yet, we're going to work only with anonymous carts in this section. | ||
|
||
In your UI, on product list items, the product detail page, or both, you will add a button, which usually says something like "Add to Cart". This button must invoke logic that decides which GraphQL mutation to use: | ||
- If you already have an anonymous cart ID and token in your application state, call the `addCartItems` mutation. | ||
- If you do not have an anonymous cart ID and token in your application state, call the `createCart` mutation. | ||
|
||
Defining these mutations looks something like this: | ||
|
||
```graphql | ||
mutation createCartMutation($input: CreateCartInput!) { | ||
createCart(input: $input) { | ||
cart { | ||
...CartFragment | ||
} | ||
incorrectPriceFailures { | ||
...IncorrectPriceFailuresFragment | ||
} | ||
minOrderQuantityFailures { | ||
...MinOrderQuantityFailuresFragment | ||
} | ||
token | ||
} | ||
} | ||
|
||
mutation addCartItemsMutation($input: AddCartItemsInput!) { | ||
addCartItems(input: $input) { | ||
cart { | ||
...CartFragment | ||
} | ||
incorrectPriceFailures { | ||
...IncorrectPriceFailuresFragment | ||
} | ||
minOrderQuantityFailures { | ||
...MinOrderQuantityFailuresFragment | ||
} | ||
} | ||
} | ||
|
||
fragment CartFragment on Cart { | ||
_id | ||
items { | ||
...CartItemConnectionFragment | ||
} | ||
totalItemQuantity | ||
} | ||
|
||
fragment CartItemConnectionFragment on CartItemConnection { | ||
pageInfo { | ||
hasNextPage | ||
endCursor | ||
} | ||
edges { | ||
node { | ||
_id | ||
productConfiguration { | ||
productId | ||
productVariantId | ||
} | ||
attributes { | ||
label | ||
value | ||
} | ||
createdAt | ||
inventoryAvailableToSell | ||
isBackorder | ||
isLowQuantity | ||
isSoldOut | ||
imageURLs { | ||
thumbnail | ||
} | ||
price { | ||
displayAmount | ||
} | ||
priceWhenAdded { | ||
displayAmount | ||
} | ||
quantity | ||
subtotal { | ||
displayAmount | ||
} | ||
title | ||
productVendor | ||
variantTitle | ||
optionTitle | ||
} | ||
} | ||
} | ||
|
||
fragment IncorrectPriceFailuresFragment on IncorrectPriceFailureDetails { | ||
currentPrice { | ||
displayAmount | ||
} | ||
providedPrice { | ||
displayAmount | ||
} | ||
} | ||
|
||
fragment MinOrderQuantityFailuresFragment on MinOrderQuantityFailureDetails { | ||
minOrderQuantity | ||
quantity | ||
} | ||
``` | ||
|
||
If you call the `createCart` mutation and get a success response, store the `cart._id` and `token` from the response in persistent app state tied to the browser or device, for example, `localStorage` or a cookie. Then the next time "Add to Cart" is clicked, your logic will see the cart ID and token and choose to call the `addCartItems` mutation. | ||
|
||
Regardless of whether you are creating a new cart with items or adding items to an existing cart, you must check for `incorrectPriceFailures` and `minOrderQuantityFailures` in the response. The server may have added only some items to the cart but been unable to add other items. If any items could not be added because you tried to add them at an incorrect price, there will be data in `incorrectPriceFailures` that you can use to show a message to the shopper. This can happen if a price changed after the page was loaded. If any items could not be added because you tried to add fewer than the minimum purchase quantity to the cart, there will be data in `minOrderQuantityFailures` that you can use to show a message to the shopper. They can then increment the quantity and attempt to add it again. | ||
|
||
Next Task: [Build a cart page](./storefront-cart-page.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Storefront UI Development | ||
## Add and configure Apollo Client | ||
|
||
### Index | ||
This article is part of the [Storefront UI Development Guide](./storefront-intro.md). | ||
- Previous Task: *None* | ||
- Next Task: [Build a product listing page](./storefront-product-listing-page.md) | ||
|
||
### Overview | ||
To add Apollo Client to your UI app, read the [excellent Apollo docs](https://www.apollographql.com/docs/react/essentials/get-started.html). For local development, the Reaction GraphQL endpoint `uri` is `http://localhost:3000/graphql`, but we recommend storing that value in app config where it can be set differently per environment. | ||
|
||
For your test query, try this: | ||
|
||
```js | ||
import gql from "graphql-tag"; | ||
|
||
const testQuery = gql`{ | ||
primaryShop { | ||
_id | ||
name | ||
} | ||
}`; | ||
|
||
client | ||
.query({ query: testQuery }) | ||
.then(result => console.log(result)); | ||
``` | ||
|
||
> If it doesn't work in your storefront UI code, try it directly in the GraphQL Playground at http://localhost:3000/graphql. If it works there, then check over your Apollo Client setup code again and check for any errors. | ||
Assuming your test query works, you're ready to start building your storefront UI. You will eventually need to configure authentication, but most of a storefront UI can be built without authenticating, so we'll do that later. | ||
|
||
Next Task: [Build a product listing page](./storefront-product-listing-page.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Storefront UI Development | ||
## Implement cart modification | ||
|
||
### Index | ||
This article is part of the [Storefront UI Development Guide](./storefront-intro.md). | ||
- Previous Task: [Build a cart page](./storefront-cart-page.md) | ||
- Next Task: [Build a checkout page](./storefront-checkout-page.md) | ||
|
||
### Overview | ||
Now that a shopper can view their cart, they'll likely want to change it. They already have the ability to add additional items to it, but at some point they'll want to change the quantity for an item or remove it entirely. We'll implement those actions in this task. There are additional cart mutations that will happen during a checkout flow, which we'll implement later. | ||
|
||
### Change the quantity for a cart item | ||
|
||
The quantity change mutation is usually invoked by clicking a quantity increment or decrement button or entering or clicking a specific quantity. Regardless of what you do for the UI, all you need to do is figure out what new quantity the shopper wants, and then pass it to the `updateCartItemsQuantity` mutation. | ||
|
||
```graphql | ||
mutation updateCartItemsQuantityMutation($input: UpdateCartItemsQuantityInput!) { | ||
updateCartItemsQuantity(input: $input) { | ||
cart { | ||
...CartFragment | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Where the `input` variable looks like this: | ||
|
||
```js | ||
{ | ||
cartId, // from application state | ||
items: [ | ||
{ cartItemId, quantity } | ||
], | ||
token // from application state | ||
} | ||
``` | ||
|
||
`cartItemId` is the `item._id` and `quantity` is the new desired quantity, which must be an integer of 0 or greater. A quantity of `0` removes the item, but we recommend calling the `removeCartItems` mutation instead. | ||
|
||
### Remove a cart item | ||
|
||
Removing a cart item is usually done by clicking a "Remove" button on the cart item UI. This should invoke the `removeCartItems` mutation. | ||
|
||
```graphql | ||
mutation removeCartItemsMutation($input: RemoveCartItemsInput!) { | ||
removeCartItems(input: $input) { | ||
cart { | ||
...CartFragment | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Where the `input` variable looks like this: | ||
|
||
```js | ||
{ | ||
cartId, // from application state | ||
cartItemIds: [], | ||
token // from application state | ||
} | ||
``` | ||
|
||
`cartItemIds` is an array of IDs from `item._id`. | ||
|
||
Next Task: [Build a checkout page](./storefront-checkout-page.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Storefront UI Development | ||
## Build a cart page | ||
|
||
### Index | ||
This article is part of the [Storefront UI Development Guide](./storefront-intro.md). | ||
- Previous Task: [Add a way to add an item to a cart](./storefront-add-to-cart.md) | ||
- Next Task: [Implement cart modification](./storefront-cart-modification.md) | ||
|
||
### Overview | ||
After a shopper has clicked "Add to Cart", they are going to want to now see their cart. This could be a sidebar component, a modal, or a full page. Either way, the data loading is similar. You will do one query for cart data, with pagination on the `cart.items` connection. | ||
|
||
```graphql | ||
query anonymousCartByCartIdQuery($cartId: ID!, $token: String!, $itemsAfterCursor: ConnectionCursor) { | ||
cart: anonymousCartByCartId(cartId: $cartId, token: $token) { | ||
items(first: 20, after: $itemsAfterCursor) { | ||
...CartItemConnectionFragment | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Typically we recommend an infinite scrolling style pagination for cart items. When the user is scrolling and nears the bottom of the list, refetch this query with `itemsAfterCursor` variable set to the `cursor` from the last item's edge. | ||
|
||
Next Task: [Implement cart modification](./storefront-cart-modification.md) |
Oops, something went wrong.