Skip to content

Commit 6ed73ba

Browse files
author
Sanjeev Yadav
committed
feat: Write addProductsToCart mutation logic
1 parent b678e90 commit 6ed73ba

File tree

5 files changed

+126
-15
lines changed

5 files changed

+126
-15
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { gql } from '@apollo/client';
2+
3+
export interface AddProductsToCartDataType {
4+
addProductsToCart: {
5+
cart: {
6+
items: Array<{
7+
id: string;
8+
product: {
9+
name: string;
10+
sku: string;
11+
};
12+
quantity: number;
13+
}>;
14+
};
15+
};
16+
}
17+
18+
export interface AddProductsToCartVars {
19+
cartId: string;
20+
cartItems: Array<CartItemInputType>;
21+
}
22+
23+
export interface CartItemInputType {
24+
quantity: number;
25+
sku: string;
26+
}
27+
28+
export const ADD_PRODUCTS_TO_CART = gql`
29+
mutation AddProductsToCart($cartId: String!, $cartItems: [CartItemInput!]!) {
30+
addProductsToCart(cartId: $cartId, cartItems: $cartItems) {
31+
cart {
32+
items {
33+
id
34+
product {
35+
name
36+
sku
37+
}
38+
quantity
39+
}
40+
}
41+
}
42+
}
43+
`;

src/apollo/queries/getProductDetails.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@ export interface ProductDetailsType {
1919
id: number;
2020
sku: string;
2121
name: string;
22+
type: ProductTypeEnum;
2223
description: {
2324
html: string;
2425
};
2526
price_range: PriceRangeType;
2627
media_gallery: Array<MediaGalleryItemType>;
2728
}
2829

30+
export enum ProductTypeEnum {
31+
SIMPLE = 'SimpleProduct',
32+
}
33+
2934
export const GET_PRODUCT_DETAILS = gql`
3035
query GetProductDetails($sku: String) {
3136
products(filter: { sku: { eq: $sku } }) {
@@ -36,6 +41,7 @@ export const GET_PRODUCT_DETAILS = gql`
3641
description {
3742
html
3843
}
44+
type: __typename
3945
price_range {
4046
maximum_price {
4147
final_price {

src/i18n/locales/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@
4949
"productDetailsScreen": {
5050
"appbarTitle": "Product Details",
5151
"addToCart": "Add To Cart",
52-
"guestUserPromptMessage": "In order to add product to cart, please login or create new account"
52+
"guestUserPromptMessage": "In order to add product to cart, please login or create new account",
53+
"productTypeNotSupported": "Currently only Simple products are supported",
54+
"addToCartSuccessful": "Product added to cart",
55+
"addToCartError": "Unable to add product to cart, something went wrong."
5356
},
5457
"productListScreen": {
5558
"appbarTitle": "Products"

src/logic/cart/useCart.ts

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,73 @@
11
import { useEffect } from 'react';
2-
import { useLazyQuery, useQuery } from '@apollo/client';
2+
import { useLazyQuery, useMutation, useQuery } from '@apollo/client';
3+
import Toast from 'react-native-simple-toast';
34
import {
45
IsLoggedInDataType,
56
IS_LOGGED_IN,
67
} from '../../apollo/queries/isLoggedIn';
78
import { GetCartDataType, GET_CART } from '../../apollo/queries/getCart';
9+
import {
10+
AddProductsToCartDataType,
11+
AddProductsToCartVars,
12+
ADD_PRODUCTS_TO_CART,
13+
CartItemInputType,
14+
} from '../../apollo/mutations/addProductsToCart';
15+
import { translate } from '../../i18n';
816

917
interface Result {
10-
data: GetCartDataType | undefined;
18+
cartData: GetCartDataType | undefined;
19+
loading: boolean;
20+
isLoggedIn: boolean;
21+
addProductsToCart(arg0: CartItemInputType): void;
1122
}
1223

1324
export const useCart = (): Result => {
1425
const { data: { isLoggedIn = false } = {} } = useQuery<IsLoggedInDataType>(
1526
IS_LOGGED_IN,
1627
);
17-
const [fetchCart, { data }] = useLazyQuery<GetCartDataType>(GET_CART);
28+
const [fetchCart, { data: cartData }] = useLazyQuery<GetCartDataType>(
29+
GET_CART,
30+
);
31+
const [_addProductsToCart, { loading, data }] = useMutation<
32+
AddProductsToCartDataType,
33+
AddProductsToCartVars
34+
>(ADD_PRODUCTS_TO_CART, {
35+
onCompleted() {
36+
Toast.show(
37+
translate('productDetailsScreen.addToCartSuccessful', Toast.LONG),
38+
);
39+
},
40+
onError(_error) {
41+
Toast.show(
42+
translate(
43+
_error.message || 'productDetailsScreen.addToCartError',
44+
Toast.LONG,
45+
),
46+
);
47+
},
48+
});
1849

1950
useEffect(() => {
2051
if (isLoggedIn) {
2152
fetchCart();
2253
}
2354
}, [isLoggedIn]);
2455

56+
const addProductsToCart = (productToAdd: CartItemInputType) => {
57+
if (isLoggedIn && cartData?.customerCart.id) {
58+
_addProductsToCart({
59+
variables: {
60+
cartId: cartData.customerCart.id,
61+
cartItems: [productToAdd],
62+
},
63+
});
64+
}
65+
};
66+
2567
return {
26-
data,
68+
addProductsToCart,
69+
isLoggedIn,
70+
cartData,
71+
loading,
2772
};
2873
};

src/screens/ProductDetailsScreen/ProductDetailsScreen.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@ import { Text, ThemeContext, Button } from 'react-native-elements';
44
import { RouteProp } from '@react-navigation/native';
55
import { StackNavigationProp } from '@react-navigation/stack';
66
import HTML from 'react-native-render-html';
7-
import { useQuery } from '@apollo/client';
7+
import Toast from 'react-native-simple-toast';
88
import { MediaGallery, GenericTemplate } from '../../components';
99
import { SPACING } from '../../constants';
1010
import { AppStackParamList, Routes } from '../../navigation';
1111
import { useProductDetails } from '../../logic/products/useProductDetails';
1212
import { getPriceStringFromPriceRange, showLoginPrompt } from '../../logic';
1313
import { translate } from '../../i18n';
14-
import {
15-
IsLoggedInDataType,
16-
IS_LOGGED_IN,
17-
} from '../../apollo/queries/isLoggedIn';
14+
import { useCart } from '../../logic/cart/useCart';
15+
import { ProductTypeEnum } from '../../apollo/queries/getProductDetails';
1816

1917
type Props = {
2018
navigation: StackNavigationProp<
@@ -34,28 +32,43 @@ const ProductDetailsScreen = ({
3432
},
3533
}: Props): React.ReactElement => {
3634
const {
37-
getProductDetails,
38-
productDetails,
39-
loading,
4035
error,
36+
loading,
37+
productDetails,
38+
getProductDetails,
4139
} = useProductDetails({
4240
sku,
4341
});
44-
const { data } = useQuery<IsLoggedInDataType>(IS_LOGGED_IN);
42+
const {
43+
isLoggedIn,
44+
addProductsToCart,
45+
loading: addProductsToCartLoading,
46+
} = useCart();
4547
const { theme } = useContext(ThemeContext);
4648

4749
useEffect(() => {
4850
getProductDetails();
4951
}, []);
5052

5153
const handleAddToCart = () => {
52-
if (!data?.isLoggedIn) {
54+
if (!isLoggedIn) {
5355
showLoginPrompt(
5456
translate('productDetailsScreen.guestUserPromptMessage'),
5557
navigation,
5658
);
5759
return;
5860
}
61+
62+
if (productDetails?.type === ProductTypeEnum.SIMPLE) {
63+
addProductsToCart({
64+
quantity: 1,
65+
sku: productDetails.sku,
66+
});
67+
} else {
68+
Toast.show(
69+
translate('productDetailsScreen.productTypeNotSupported', Toast.LONG),
70+
);
71+
}
5972
};
6073

6174
return (
@@ -65,6 +78,7 @@ const ProductDetailsScreen = ({
6578
errorMessage={error?.message}
6679
footer={
6780
<Button
81+
loading={addProductsToCartLoading}
6882
containerStyle={styles.noBorderRadius}
6983
buttonStyle={styles.noBorderRadius}
7084
title={translate('productDetailsScreen.addToCart')}

0 commit comments

Comments
 (0)