react-native-srschat 0.1.56 → 0.1.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/productCard.js +91 -39
- package/lib/commonjs/components/productCard.js.map +1 -1
- package/lib/commonjs/components/testProductCard.js +60 -0
- package/lib/commonjs/components/testProductCard.js.map +1 -0
- package/lib/commonjs/components/testing.js +35 -8
- package/lib/commonjs/components/testing.js.map +1 -1
- package/lib/module/components/productCard.js +91 -39
- package/lib/module/components/productCard.js.map +1 -1
- package/lib/module/components/testProductCard.js +52 -0
- package/lib/module/components/testProductCard.js.map +1 -0
- package/lib/module/components/testing.js +36 -9
- package/lib/module/components/testing.js.map +1 -1
- package/lib/typescript/components/productCard.d.ts.map +1 -1
- package/lib/typescript/components/testProductCard.d.ts +3 -0
- package/lib/typescript/components/testProductCard.d.ts.map +1 -0
- package/lib/typescript/components/testing.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/productCard.js +91 -42
- package/src/components/testProductCard.js +55 -0
- package/src/components/testing.js +45 -14
|
@@ -24,7 +24,8 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
24
24
|
if (minPackStr) {
|
|
25
25
|
const minPackNum = parseFloat(minPackStr);
|
|
26
26
|
if (!isNaN(minPackNum) && minPackNum > 1.0) {
|
|
27
|
-
|
|
27
|
+
// Round to 2 decimal places for decimal min pack quantities
|
|
28
|
+
return Math.round(minPackNum * 100) / 100;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
return 1; // Default min pack quantity for individual purchase
|
|
@@ -50,6 +51,7 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
50
51
|
const currentMinPackQtyForSelectedUom = getMinPackQtyForUom(selectedUom);
|
|
51
52
|
|
|
52
53
|
const [quantity, setQuantity] = useState(0);
|
|
54
|
+
const [quantityText, setQuantityText] = useState("0"); // Track the text input separately
|
|
53
55
|
|
|
54
56
|
// Add keyboard listeners to detect when keyboard appears/disappears
|
|
55
57
|
useEffect(() => {
|
|
@@ -80,49 +82,67 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
80
82
|
// Called on every keystroke in the quantity input
|
|
81
83
|
const handleQuantityChange = (text) => {
|
|
82
84
|
const rawValue = text.trim();
|
|
85
|
+
|
|
86
|
+
// Update the text display immediately
|
|
87
|
+
setQuantityText(rawValue);
|
|
88
|
+
|
|
89
|
+
// Handle empty input
|
|
83
90
|
if (rawValue === "") {
|
|
84
91
|
setQuantity(0);
|
|
85
92
|
return;
|
|
86
93
|
}
|
|
87
|
-
|
|
94
|
+
|
|
95
|
+
// Allow partial decimal inputs like "." or "1."
|
|
96
|
+
if (rawValue === "." || rawValue.endsWith(".")) {
|
|
97
|
+
// Don't update quantity state for partial decimal inputs, just keep the text
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const numericValue = parseFloat(rawValue);
|
|
88
102
|
if (!isNaN(numericValue) && numericValue >= 0) {
|
|
89
|
-
|
|
103
|
+
// Round to 2 decimal places to handle decimal min pack quantities
|
|
104
|
+
setQuantity(Math.round(numericValue * 100) / 100);
|
|
90
105
|
} else {
|
|
91
|
-
|
|
106
|
+
// Invalid input, reset quantity but keep the text for user feedback
|
|
107
|
+
setQuantity(0);
|
|
92
108
|
}
|
|
93
109
|
};
|
|
94
110
|
|
|
95
111
|
// Called when the quantity input loses focus (onEndEditing)
|
|
96
112
|
const handleQuantityBlur = () => {
|
|
97
|
-
const currentQuantityFromState = quantity;
|
|
98
|
-
const uom = selectedUom;
|
|
99
|
-
const minPack = getMinPackQtyForUom(uom);
|
|
100
113
|
const isProdValid = prod.inventory_info?.is_valid || false;
|
|
101
114
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
// Parse the final text input
|
|
116
|
+
const rawValue = quantityText.trim();
|
|
117
|
+
let finalQuantity = 0;
|
|
118
|
+
|
|
119
|
+
if (rawValue !== "") {
|
|
120
|
+
const numericValue = parseFloat(rawValue);
|
|
121
|
+
if (!isNaN(numericValue) && numericValue >= 0) {
|
|
122
|
+
finalQuantity = Math.round(numericValue * 100) / 100;
|
|
123
|
+
}
|
|
105
124
|
}
|
|
106
125
|
|
|
107
|
-
|
|
108
|
-
|
|
126
|
+
// Only basic validation - don't auto-correct to min pack quantities
|
|
127
|
+
if (!isProdValid) {
|
|
128
|
+
setQuantity(0);
|
|
129
|
+
setQuantityText("0");
|
|
109
130
|
return;
|
|
110
131
|
}
|
|
111
132
|
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (currentQuantityFromState > 0 && adjustedValue === 0) {
|
|
118
|
-
adjustedValue = minPack;
|
|
119
|
-
}
|
|
133
|
+
// Just ensure quantity is not negative, but allow any positive decimal value
|
|
134
|
+
if (finalQuantity < 0) {
|
|
135
|
+
setQuantity(0);
|
|
136
|
+
setQuantityText("0");
|
|
137
|
+
return;
|
|
120
138
|
}
|
|
121
139
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
140
|
+
// Update both states with the final parsed value
|
|
141
|
+
setQuantity(finalQuantity);
|
|
142
|
+
setQuantityText(finalQuantity.toString());
|
|
143
|
+
|
|
144
|
+
// Keep the user's input as-is for valid products
|
|
145
|
+
// Validation and alerts will happen in handleAddToCart
|
|
126
146
|
};
|
|
127
147
|
|
|
128
148
|
const incrementQuantity = () => {
|
|
@@ -131,13 +151,28 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
131
151
|
|
|
132
152
|
setQuantity(prevQuantity => {
|
|
133
153
|
let newQuantity;
|
|
134
|
-
|
|
154
|
+
|
|
155
|
+
if (prevQuantity === 0) {
|
|
156
|
+
// If starting from 0, go to first min pack
|
|
135
157
|
newQuantity = minPackForUom;
|
|
136
|
-
} else {
|
|
158
|
+
} else if (minPackForUom <= 1) {
|
|
159
|
+
// If min pack is 1 or less, just increment by min pack
|
|
137
160
|
newQuantity = prevQuantity + minPackForUom;
|
|
161
|
+
} else {
|
|
162
|
+
// Find the next valid multiple of min pack quantity
|
|
163
|
+
const nextMultiple = Math.ceil(prevQuantity / minPackForUom) * minPackForUom;
|
|
164
|
+
// If current quantity is already a perfect multiple, go to next multiple
|
|
165
|
+
if (Math.abs(prevQuantity % minPackForUom) < 0.01) {
|
|
166
|
+
newQuantity = prevQuantity + minPackForUom;
|
|
167
|
+
} else {
|
|
168
|
+
newQuantity = nextMultiple;
|
|
169
|
+
}
|
|
138
170
|
}
|
|
139
171
|
|
|
140
|
-
|
|
172
|
+
// Round to 2 decimal places to handle decimal min pack quantities
|
|
173
|
+
const finalQuantity = Math.round(newQuantity * 100) / 100;
|
|
174
|
+
setQuantityText(finalQuantity.toString());
|
|
175
|
+
return finalQuantity;
|
|
141
176
|
});
|
|
142
177
|
};
|
|
143
178
|
|
|
@@ -146,21 +181,33 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
146
181
|
const minPackForUom = getMinPackQtyForUom(uomForCalc);
|
|
147
182
|
|
|
148
183
|
setQuantity(prevQuantity => {
|
|
149
|
-
if (prevQuantity === 0)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (newQuantity < 0) {
|
|
154
|
-
newQuantity = 0;
|
|
184
|
+
if (prevQuantity === 0) {
|
|
185
|
+
setQuantityText("0");
|
|
186
|
+
return 0; // Cannot go below 0
|
|
155
187
|
}
|
|
188
|
+
|
|
189
|
+
let newQuantity;
|
|
156
190
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
191
|
+
if (minPackForUom <= 1) {
|
|
192
|
+
// If min pack is 1 or less, just decrement by min pack
|
|
193
|
+
newQuantity = Math.max(0, prevQuantity - minPackForUom);
|
|
194
|
+
} else {
|
|
195
|
+
// Find the previous valid multiple of min pack quantity
|
|
196
|
+
const prevMultiple = Math.floor(prevQuantity / minPackForUom) * minPackForUom;
|
|
197
|
+
|
|
198
|
+
// If current quantity is already a perfect multiple, go to previous multiple
|
|
199
|
+
if (Math.abs(prevQuantity % minPackForUom) < 0.01) {
|
|
200
|
+
newQuantity = Math.max(0, prevQuantity - minPackForUom);
|
|
201
|
+
} else {
|
|
202
|
+
// If not a perfect multiple, go to the lower multiple
|
|
203
|
+
newQuantity = prevMultiple;
|
|
204
|
+
}
|
|
161
205
|
}
|
|
162
206
|
|
|
163
|
-
|
|
207
|
+
// Round to 2 decimal places to handle decimal min pack quantities
|
|
208
|
+
const finalQuantity = Math.round(newQuantity * 100) / 100;
|
|
209
|
+
setQuantityText(finalQuantity.toString());
|
|
210
|
+
return finalQuantity;
|
|
164
211
|
});
|
|
165
212
|
};
|
|
166
213
|
|
|
@@ -201,8 +248,9 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
201
248
|
});
|
|
202
249
|
};
|
|
203
250
|
|
|
204
|
-
|
|
205
|
-
|
|
251
|
+
// Check if quantity is valid for min pack requirements
|
|
252
|
+
if (currentMinPackQtyForSelectedUom > 1 && Math.abs(quantity % currentMinPackQtyForSelectedUom) > 0.01) {
|
|
253
|
+
const roundedResult = Math.round(Math.ceil(quantity / currentMinPackQtyForSelectedUom) * currentMinPackQtyForSelectedUom * 100) / 100;
|
|
206
254
|
|
|
207
255
|
Alert.alert(
|
|
208
256
|
`Item #${prod.part_number} is sold in multiples of ${currentMinPackQtyForSelectedUom} ${selectedUom}`,
|
|
@@ -211,7 +259,7 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
211
259
|
{
|
|
212
260
|
text: 'Cancel',
|
|
213
261
|
onPress: () => {
|
|
214
|
-
|
|
262
|
+
// Keep the user's input, don't reset to 0
|
|
215
263
|
},
|
|
216
264
|
style: 'cancel',
|
|
217
265
|
},
|
|
@@ -246,6 +294,7 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
246
294
|
|
|
247
295
|
// Always set quantity to 0 when UOM changes
|
|
248
296
|
setQuantity(0);
|
|
297
|
+
setQuantityText("0");
|
|
249
298
|
};
|
|
250
299
|
|
|
251
300
|
const openUomPicker = () => {
|
|
@@ -376,7 +425,7 @@ export const ProductCard = ({ prod, onFocusQuantityInput, messageId }) => {
|
|
|
376
425
|
</TouchableOpacity>
|
|
377
426
|
|
|
378
427
|
<TextInput
|
|
379
|
-
value={
|
|
428
|
+
value={quantityText}
|
|
380
429
|
onChangeText={handleQuantityChange}
|
|
381
430
|
onEndEditing={handleQuantityBlur}
|
|
382
431
|
keyboardType="numeric"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, ScrollView, StyleSheet, Text } from 'react-native';
|
|
3
|
+
import { ProductCard } from './productCard';
|
|
4
|
+
|
|
5
|
+
const mockProduct = {
|
|
6
|
+
"part_number": "AEQO177",
|
|
7
|
+
"inventory_info": {
|
|
8
|
+
"default_uom": "EA",
|
|
9
|
+
"is_valid": true,
|
|
10
|
+
"info_by_uom": {
|
|
11
|
+
"EA": {
|
|
12
|
+
"gross_price": 7.83,
|
|
13
|
+
"net_price": 7.83,
|
|
14
|
+
"is_on_sale": false,
|
|
15
|
+
"quantity_available": 0,
|
|
16
|
+
"discounts": null,
|
|
17
|
+
"min_pack_qty": 1.5
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"product_details": {
|
|
22
|
+
"product_name": "Aladdin Hayward SPX1600S SuperPump Lid Gasket | O-177-2",
|
|
23
|
+
"part_number": "AEQO177",
|
|
24
|
+
"manufacturer_id": "O-177-2",
|
|
25
|
+
"heritage_link": "https://www.heritagepoolplus.com/aeqo177-aladdin-o-ring-o-177-o-177-2-o-177-2",
|
|
26
|
+
"image_url": "https://media.heritageplus.com/image/upload/v1668157956/image/AEQO177_0.jpg"
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const TestProductCard = () => {
|
|
31
|
+
return (
|
|
32
|
+
<ScrollView style={styles.container}>
|
|
33
|
+
<Text style={styles.title}>Test Product Card</Text>
|
|
34
|
+
<ProductCard
|
|
35
|
+
prod={mockProduct}
|
|
36
|
+
onFocusQuantityInput={(partNumber) => console.log('Focus on:', partNumber)}
|
|
37
|
+
messageId="test-message-123"
|
|
38
|
+
/>
|
|
39
|
+
</ScrollView>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const styles = StyleSheet.create({
|
|
44
|
+
container: {
|
|
45
|
+
flex: 1,
|
|
46
|
+
backgroundColor: '#f6f6f6',
|
|
47
|
+
padding: 16,
|
|
48
|
+
},
|
|
49
|
+
title: {
|
|
50
|
+
fontSize: 18,
|
|
51
|
+
fontWeight: 'bold',
|
|
52
|
+
marginBottom: 16,
|
|
53
|
+
textAlign: 'center',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { View, Button, StyleSheet, TouchableOpacity, Text } from 'react-native';
|
|
2
|
+
import { View, Button, StyleSheet, TouchableOpacity, Text, ScrollView } from 'react-native';
|
|
3
|
+
import { ProductCard } from './productCard';
|
|
3
4
|
|
|
4
5
|
export const Testing = ({ onProductCardClick, onAddToCartClick }) => {
|
|
5
6
|
|
|
@@ -14,7 +15,8 @@ export const Testing = ({ onProductCardClick, onAddToCartClick }) => {
|
|
|
14
15
|
"net_price": 7.83,
|
|
15
16
|
"is_on_sale": false,
|
|
16
17
|
"quantity_available": 0,
|
|
17
|
-
"discounts": null
|
|
18
|
+
"discounts": null,
|
|
19
|
+
"min_pack_qty": 1.5
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
},
|
|
@@ -28,25 +30,52 @@ export const Testing = ({ onProductCardClick, onAddToCartClick }) => {
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
return (
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
<ScrollView style={styles.container}>
|
|
34
|
+
<Text style={styles.title}>Test Product Card</Text>
|
|
35
|
+
|
|
36
|
+
{/* Display the actual product card */}
|
|
37
|
+
<View style={styles.productCardContainer}>
|
|
38
|
+
<ProductCard
|
|
39
|
+
prod={product}
|
|
40
|
+
onFocusQuantityInput={(partNumber) => console.log('Focus on:', partNumber)}
|
|
41
|
+
messageId="test-message-123"
|
|
42
|
+
/>
|
|
43
|
+
</View>
|
|
44
|
+
|
|
45
|
+
{/* Test buttons */}
|
|
46
|
+
<View style={styles.buttonContainer}>
|
|
47
|
+
<TouchableOpacity style={styles.button} onPress={() => onProductCardClick(product)}>
|
|
48
|
+
<Text style={styles.buttonText}>Product Card Click</Text>
|
|
49
|
+
</TouchableOpacity>
|
|
50
|
+
<TouchableOpacity style={styles.button} onPress={() => onAddToCartClick({"quantity":1,"product":product})}>
|
|
51
|
+
<Text style={styles.buttonText}>Add to Cart</Text>
|
|
52
|
+
</TouchableOpacity>
|
|
53
|
+
</View>
|
|
54
|
+
</ScrollView>
|
|
39
55
|
);
|
|
40
56
|
};
|
|
41
57
|
|
|
42
58
|
const styles = StyleSheet.create({
|
|
43
59
|
container: {
|
|
60
|
+
backgroundColor: '#f6f6f6',
|
|
61
|
+
borderTopWidth: 1,
|
|
62
|
+
borderTopColor: '#DDD',
|
|
63
|
+
},
|
|
64
|
+
title: {
|
|
65
|
+
fontSize: 18,
|
|
66
|
+
fontWeight: 'bold',
|
|
67
|
+
textAlign: 'center',
|
|
68
|
+
padding: 16,
|
|
69
|
+
},
|
|
70
|
+
productCardContainer: {
|
|
71
|
+
paddingHorizontal: 16,
|
|
72
|
+
},
|
|
73
|
+
buttonContainer: {
|
|
44
74
|
flexDirection: 'row',
|
|
45
75
|
alignItems: 'center',
|
|
46
76
|
justifyContent: 'space-evenly',
|
|
47
77
|
paddingHorizontal: 16,
|
|
48
|
-
|
|
49
|
-
borderTopColor: '#DDD',
|
|
78
|
+
paddingVertical: 20,
|
|
50
79
|
},
|
|
51
80
|
button: {
|
|
52
81
|
backgroundColor: "#d4d4d4",
|
|
@@ -54,7 +83,9 @@ const styles = StyleSheet.create({
|
|
|
54
83
|
paddingHorizontal: 12,
|
|
55
84
|
borderRadius: 5,
|
|
56
85
|
alignItems: "center",
|
|
57
|
-
|
|
58
|
-
|
|
86
|
+
},
|
|
87
|
+
buttonText: {
|
|
88
|
+
fontSize: 14,
|
|
89
|
+
fontWeight: 'bold',
|
|
59
90
|
},
|
|
60
91
|
});
|