Skip to content

Commit cf31378

Browse files
author
Thiago Lopes
committed
Deleted removeFromCart method, added qty attribute on colors[] & added increase/decreaseQty methods
1 parent 1815545 commit cf31378

File tree

7 files changed

+304
-118
lines changed

7 files changed

+304
-118
lines changed

src/components/ShoppingCard.tsx

Lines changed: 73 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMemo, useContext } from 'react'
1+
import { useMemo } from 'react'
22
import {
33
StyleSheet,
44
Text,
@@ -7,17 +7,17 @@ import {
77
Image,
88
TouchableOpacity
99
} from 'react-native'
10+
import { useNavigation } from '@react-navigation/native'
11+
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
1012
import Icon from 'react-native-vector-icons/FontAwesome6'
11-
import { ProductCardProps } from '@Data/types'
13+
import { ProductCardProps, GlobalStateContextProps } from '@Data/types'
1214
import { colors } from '@Theme/colors'
1315
import formatUSD from '@Utils/formatPrice'
1416
import BlobBackground from '@Assets/brand/backgroundBlob.svg'
15-
import { GlobalContext } from '@Context/GlobalState'
1617

17-
type ShoppingCardProps = ProductCardProps & {
18-
increaseQty: () => void
19-
decreaseQty: () => void
20-
} & ViewProps
18+
type ShoppingCardProps = ProductCardProps &
19+
Pick<GlobalStateContextProps, 'decreaseQty' | 'increaseQty'> &
20+
ViewProps
2121

2222
const ShoppingCard = ({
2323
id,
@@ -31,73 +31,81 @@ const ShoppingCard = ({
3131
decreaseQty,
3232
...rest
3333
}: ShoppingCardProps) => {
34-
const { removeFromCart } = useContext(GlobalContext)
34+
const navigation = useNavigation<NativeStackNavigationProp<any>>()
35+
36+
function goToDetails() {
37+
navigation.push('Details', { index })
38+
}
3539

3640
return useMemo(
3741
() => (
38-
<View>
39-
<View style={styles.container} {...rest}>
40-
<View style={styles.productVisual}>
41-
<BlobBackground
42-
fill={colors[productColors[0].blobBg]}
43-
style={styles.productBlob}
44-
/>
45-
46-
<Image
47-
source={imgUrl}
48-
style={[
49-
styles.productImg,
50-
{ maxWidth: brand === 'Beats' ? 39 : 49 }
51-
]}
52-
/>
53-
</View>
42+
<View style={styles.container} {...rest}>
43+
<TouchableOpacity
44+
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
45+
onPress={goToDetails}
46+
style={styles.productVisual}
47+
>
48+
<BlobBackground
49+
fill={colors[productColors[0].blobBg]}
50+
style={styles.productBlob}
51+
/>
5452

55-
<View style={styles.productInfo}>
56-
<View style={styles.productNamePrice}>
57-
<Text
58-
style={styles.productName}
59-
numberOfLines={1}
60-
ellipsizeMode="clip"
61-
>
62-
{name}
63-
</Text>
53+
<Image
54+
source={imgUrl}
55+
style={[
56+
styles.productImg,
57+
{ maxWidth: brand === 'Beats' ? 39 : 49 }
58+
]}
59+
/>
60+
</TouchableOpacity>
6461

65-
<Text
66-
style={styles.productPrice}
67-
numberOfLines={1}
68-
ellipsizeMode="clip"
69-
>
70-
{formatUSD(productColors[0].price)}
71-
</Text>
72-
</View>
62+
<View style={styles.productInfo}>
63+
<View style={styles.productNamePrice}>
64+
<Text
65+
style={styles.productName}
66+
numberOfLines={1}
67+
ellipsizeMode="clip"
68+
>
69+
{name}
70+
</Text>
7371

74-
<Text style={styles.productDescription} numberOfLines={1}>
75-
{description}
72+
<Text
73+
style={styles.productPrice}
74+
numberOfLines={1}
75+
ellipsizeMode="clip"
76+
>
77+
{formatUSD(productColors[0].price)}
7678
</Text>
7779
</View>
7880

79-
<View style={styles.actionBtns}>
80-
<TouchableOpacity
81-
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
82-
onPress={increaseQty}
83-
style={styles.actionBtn}
84-
>
85-
<Icon name="plus" size={13} color={colors.txtDarkColor} />
86-
</TouchableOpacity>
81+
<View style={styles.productDescription}>
82+
<Text style={styles.productColorQty}>
83+
Color: {productColors[0].color}
84+
</Text>
8785

88-
<TouchableOpacity
89-
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
90-
onPress={decreaseQty}
91-
style={styles.actionBtn}
92-
>
93-
<Icon name="minus" size={13} color={colors.txtDarkColor} />
94-
</TouchableOpacity>
86+
<Text style={styles.productColorQty}>
87+
Quantity: {productColors[0].quantity}
88+
</Text>
9589
</View>
9690
</View>
9791

98-
<TouchableOpacity onPress={() => removeFromCart(id)}>
99-
<Text style={styles.deleteFromCarBtn}>Remove from Cart</Text>
100-
</TouchableOpacity>
92+
<View style={styles.actionBtns}>
93+
<TouchableOpacity
94+
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
95+
onPress={() => increaseQty(id, productColors[0].color)}
96+
style={styles.actionBtn}
97+
>
98+
<Icon name="plus" size={13} color={colors.txtDarkColor} />
99+
</TouchableOpacity>
100+
101+
<TouchableOpacity
102+
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
103+
onPress={() => decreaseQty(id, productColors[0].color)}
104+
style={styles.actionBtn}
105+
>
106+
<Icon name="minus" size={13} color={colors.txtDarkColor} />
107+
</TouchableOpacity>
108+
</View>
101109
</View>
102110
),
103111
[
@@ -164,6 +172,10 @@ const styles = StyleSheet.create({
164172
color: colors.primaryColor
165173
},
166174
productDescription: {
175+
flexDirection: 'row',
176+
justifyContent: 'space-between'
177+
},
178+
productColorQty: {
167179
fontSize: 10,
168180
fontWeight: '400',
169181
fontFamily: 'Poppins_400Regular',
@@ -182,15 +194,6 @@ const styles = StyleSheet.create({
182194
backgroundColor: colors.containerColor,
183195
alignItems: 'center',
184196
justifyContent: 'center'
185-
},
186-
deleteFromCarBtn: {
187-
fontSize: 10,
188-
marginTop: 8,
189-
marginRight: 8,
190-
textAlign: 'right',
191-
fontWeight: '600',
192-
fontFamily: 'Poppins_600SemiBold',
193-
color: colors.txtDarkColor
194197
}
195198
})
196199

src/context/AppReducer.ts

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ const initialState: AppState = {
99
export enum ActionTypes {
1010
TOGGLE_FAVORITE = 'TOGGLE_FAVORITE',
1111
ADD_TO_CART = 'ADD_TO_CART',
12-
REMOVE_FROM_CART = 'REMOVE_FROM_CART',
12+
INCREASE_QTY = 'INCREASE_QTY',
13+
DECREASE_QTY = 'DECREASE_QTY',
1314
DELETE_ALL_FROM_CART = 'DELETE_ALL_FROM_CART',
1415
DELETE_ALL_FROM_FAVORITES = 'DELETE_ALL_FROM_FAVORITES'
1516
}
1617

1718
type Action =
1819
| { type: ActionTypes.TOGGLE_FAVORITE; payload: Product }
1920
| { type: ActionTypes.ADD_TO_CART; payload: Product }
20-
| { type: ActionTypes.REMOVE_FROM_CART; payload: string }
21+
| { type: ActionTypes.INCREASE_QTY; payload: { id: string; color: string } }
22+
| { type: ActionTypes.DECREASE_QTY; payload: { id: string; color: string } }
2123
| { type: ActionTypes.DELETE_ALL_FROM_CART }
2224
| { type: ActionTypes.DELETE_ALL_FROM_FAVORITES }
2325

@@ -51,14 +53,88 @@ export const AppReducer = (
5153
favorites: []
5254
}
5355
case ActionTypes.ADD_TO_CART:
54-
return {
55-
...state,
56-
cart: [...state.cart, action.payload]
56+
const { payload } = action
57+
const productExists = state.cart.some(
58+
(product) =>
59+
product.id === payload.id &&
60+
product.colors[0].color === payload.colors[0].color
61+
)
62+
63+
if (productExists) {
64+
return {
65+
...state,
66+
cart: state.cart.map((product) =>
67+
product.id === payload.id
68+
? {
69+
...product,
70+
colors: [
71+
{
72+
...product.colors[0],
73+
quantity: product.colors[0].quantity + 1
74+
}
75+
]
76+
}
77+
: product
78+
)
79+
}
80+
} else {
81+
return {
82+
...state,
83+
cart: [...state.cart, payload]
84+
}
5785
}
58-
case ActionTypes.REMOVE_FROM_CART:
86+
case ActionTypes.INCREASE_QTY:
5987
return {
6088
...state,
61-
cart: state.cart.filter((product) => product.id !== action.payload)
89+
cart: state.cart.map((product) =>
90+
product.id === action.payload.id &&
91+
product.colors[0].color === action.payload.color
92+
? {
93+
...product,
94+
colors: [
95+
{
96+
...product.colors[0],
97+
quantity: product.colors[0].quantity + 1
98+
}
99+
]
100+
}
101+
: product
102+
)
103+
}
104+
case ActionTypes.DECREASE_QTY:
105+
const { id, color } = action.payload
106+
const isQuantityOne = state.cart.some(
107+
(product) =>
108+
product.id === id &&
109+
product.colors[0].color === color &&
110+
product.colors[0].quantity === 1
111+
)
112+
113+
if (isQuantityOne) {
114+
return {
115+
...state,
116+
cart: state.cart.filter(
117+
(product) =>
118+
!(product.id === id && product.colors[0].color === color)
119+
)
120+
}
121+
} else {
122+
return {
123+
...state,
124+
cart: state.cart.map((product) =>
125+
product.id === id && product.colors[0].color === color
126+
? {
127+
...product,
128+
colors: [
129+
{
130+
...product.colors[0],
131+
quantity: product.colors[0].quantity - 1
132+
}
133+
]
134+
}
135+
: product
136+
)
137+
}
62138
}
63139
case ActionTypes.DELETE_ALL_FROM_CART:
64140
return {

src/context/GlobalState.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export const GlobalContext = createContext<GlobalStateContextProps>({
1717
toggleFavorite: () => {},
1818
deleteAllFromFavorites: () => {},
1919
addToCart: () => {},
20-
removeFromCart: () => {},
20+
increaseQty: () => {},
21+
decreaseQty: () => {},
2122
deleteAllFromCart: () => {}
2223
})
2324

@@ -49,10 +50,16 @@ export const GlobalProvider = ({ children }: GlobalStateProps) => {
4950
payload: product
5051
})
5152
}
52-
const removeFromCart = (id: string) => {
53+
const increaseQty = (id: string, color: string) => {
5354
dispatch({
54-
type: ActionTypes.REMOVE_FROM_CART,
55-
payload: id
55+
type: ActionTypes.INCREASE_QTY,
56+
payload: { id, color }
57+
})
58+
}
59+
const decreaseQty = (id: string, color: string) => {
60+
dispatch({
61+
type: ActionTypes.DECREASE_QTY,
62+
payload: { id, color }
5663
})
5764
}
5865
const deleteAllFromCart = () => {
@@ -71,7 +78,8 @@ export const GlobalProvider = ({ children }: GlobalStateProps) => {
7178
toggleFavorite,
7279
deleteAllFromFavorites,
7380
addToCart,
74-
removeFromCart,
81+
increaseQty,
82+
decreaseQty,
7583
deleteAllFromCart
7684
}}
7785
>

0 commit comments

Comments
 (0)