@whatmore-repo/whatmore-reactnative-sdk 1.0.19 → 1.0.21
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/package.json +4 -4
- package/src/api/navigation-commands/NavigationCommands.js +15 -1
- package/src/components/EventClickComponent.js +1 -1
- package/src/components/EventShoppingOverlay.js +14 -11
- package/src/components/EventShoppingView.js +1 -1
- package/src/components/EventsVerticalSwipeView.js +2 -6
- package/src/components/WhatmoreRootComponent.js +16 -9
- package/src/components/carousel-view/EventTileWithProduct.js +98 -0
- package/src/components/cta-buttons/ShopNowButton.jsx +7 -7
- package/src/components/product-tiles/ProductTileV1.js +4 -14
- package/src/icons/icon-components/CloseIcon.jsx +13 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whatmore-repo/whatmore-reactnative-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"description": "",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"react-hooks-global-state": "^2.1.0",
|
|
16
16
|
"react-native-animatable": "^1.3.3",
|
|
17
17
|
"react-native-intersection-observer": "^0.0.9",
|
|
18
|
-
"react-native-
|
|
18
|
+
"react-native-snap-carousel": "^3.9.1"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@babel/core": "^7.20.0"
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"react": "^18.2.0",
|
|
25
25
|
"react-native": "^0.72.1",
|
|
26
|
-
"react-native-
|
|
27
|
-
"react-native-
|
|
26
|
+
"react-native-svg": "13.9.0",
|
|
27
|
+
"react-native-video": "^5.2.1"
|
|
28
28
|
},
|
|
29
29
|
"author": "Shyam",
|
|
30
30
|
"license": "ISC"
|
|
@@ -3,7 +3,17 @@ import { getGlobalState } from "../../globals/useAppState_APP.js";
|
|
|
3
3
|
import { isAppBrew, isAppMaker, isPlobalApps } from "../partners/PartnerUtils.js";
|
|
4
4
|
import { appbrewNavigateToProductPageCommand } from "../partners/appbrew/AppbrewCommands.js";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
function handleClick(product, props){
|
|
7
|
+
props.setIsModalOpen(false);
|
|
8
|
+
props.onAction({
|
|
9
|
+
action: "OPEN_PRODUCT",
|
|
10
|
+
params:{
|
|
11
|
+
productId: 'gid://shopify/Product/' + product.client_product_id
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function navigateToProductPage(product, brandDomainContext, whatmoreShopId, props) {
|
|
7
17
|
const _ACTIVATE_MOCK_ = getGlobalState("activateMock");
|
|
8
18
|
if (_ACTIVATE_MOCK_) {
|
|
9
19
|
return Promise.resolve(true);
|
|
@@ -13,5 +23,9 @@ export async function navigateToProductPage(product, brandDomainContext, whatmor
|
|
|
13
23
|
return await appbrewNavigateToProductPageCommand(product, whatmoreShopId);
|
|
14
24
|
}
|
|
15
25
|
|
|
26
|
+
if(isAppMaker(brandDomainContext)){
|
|
27
|
+
return handleClick(product, props);
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
return Promise.resolve(false);
|
|
17
31
|
}
|
|
@@ -22,7 +22,7 @@ export default function EventClickComponent(props) {
|
|
|
22
22
|
{
|
|
23
23
|
modalUsed
|
|
24
24
|
?
|
|
25
|
-
<EventsVerticalSwipeView events={props.events} onAction={props.onAction} initialEventIndex={props.initialEventIndex} />
|
|
25
|
+
<EventsVerticalSwipeView setIsModalOpen={props.setIsModalOpen} isModalOpen={props.isModalOpen} events={props.events} onAction={props.onAction} initialEventIndex={props.initialEventIndex} />
|
|
26
26
|
:
|
|
27
27
|
<EventsVerticalSwipeViewNoModal events={props.events} initialEventIndex={props.initialEventIndex} />
|
|
28
28
|
}
|
|
@@ -3,6 +3,7 @@ import { Text, TouchableOpacity, View } from "react-native";
|
|
|
3
3
|
import { getGlobalState, setGlobalState, useGlobalState } from '../globals/useAppState_APP.js';
|
|
4
4
|
import AppMuteUnmuteIcon from './commons/AppMuteUnmuteIcon.js';
|
|
5
5
|
import ProductTileV1 from './product-tiles/ProductTileV1.js';
|
|
6
|
+
import CrossIcon from '../icons/icon-components/CloseIcon.jsx';
|
|
6
7
|
|
|
7
8
|
export default function EventShoppingOverlay(props) {
|
|
8
9
|
var event = props.event;
|
|
@@ -15,16 +16,18 @@ export default function EventShoppingOverlay(props) {
|
|
|
15
16
|
}}
|
|
16
17
|
>
|
|
17
18
|
{/* <Text style={{fontSize: 20, fontWeight: 'bold'}}> ABCD </Text> */}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
<View style={{
|
|
20
|
+
width: '100%',
|
|
21
|
+
flexDirection: 'row',
|
|
22
|
+
justifyContent: 'space-between',
|
|
23
|
+
alignItems: 'center',
|
|
24
|
+
backgroundColor: 'transparent',
|
|
25
|
+
paddingTop: 10,
|
|
26
|
+
}}>
|
|
27
|
+
<TouchableOpacity onPress={()=>props.setIsModalOpen(false)} style={{paddingLeft: 20}}>
|
|
28
|
+
<CrossIcon/>
|
|
29
|
+
</TouchableOpacity>
|
|
30
|
+
|
|
28
31
|
<AppMuteUnmuteIcon />
|
|
29
32
|
</View>
|
|
30
33
|
<View
|
|
@@ -60,7 +63,7 @@ export default function EventShoppingOverlay(props) {
|
|
|
60
63
|
{
|
|
61
64
|
event.products.map((product, index) => {
|
|
62
65
|
return (
|
|
63
|
-
index == 0 && <ProductTileV1
|
|
66
|
+
index == 0 && <ProductTileV1 setIsModalOpen={props.setIsModalOpen} key={index} onAction={props.onAction} event={event} product={product} />
|
|
64
67
|
);
|
|
65
68
|
})
|
|
66
69
|
}
|
|
@@ -29,7 +29,7 @@ export default function EventShoppingView(props) {
|
|
|
29
29
|
backgroundColor: 'transparent',
|
|
30
30
|
}}
|
|
31
31
|
>
|
|
32
|
-
<EventShoppingOverlay
|
|
32
|
+
<EventShoppingOverlay setIsModalOpen={props.setIsModalOpen} event={event} onAction={props.onAction} />
|
|
33
33
|
</View>
|
|
34
34
|
</View>
|
|
35
35
|
);
|
|
@@ -7,7 +7,6 @@ import EventShoppingView from './EventShoppingView.js';
|
|
|
7
7
|
import { setGlobalState } from '../globals/useAppState_APP.js';
|
|
8
8
|
|
|
9
9
|
export default function EventsVerticalSwipeView(props) {
|
|
10
|
-
const [modalVisible, setModalVisible] = React.useState(true);
|
|
11
10
|
var events = props.events;
|
|
12
11
|
return (
|
|
13
12
|
<Modal
|
|
@@ -18,10 +17,7 @@ export default function EventsVerticalSwipeView(props) {
|
|
|
18
17
|
}}
|
|
19
18
|
animationType="slide"
|
|
20
19
|
transparent={false}
|
|
21
|
-
visible={
|
|
22
|
-
onRequestClose={() => {
|
|
23
|
-
setModalVisible(!modalVisible);
|
|
24
|
-
}}
|
|
20
|
+
visible={props.isModalOpen}
|
|
25
21
|
>
|
|
26
22
|
<Swiper
|
|
27
23
|
style={{}}
|
|
@@ -48,7 +44,7 @@ export default function EventsVerticalSwipeView(props) {
|
|
|
48
44
|
backgroundColor: 'transparent'
|
|
49
45
|
}}
|
|
50
46
|
>
|
|
51
|
-
<EventShoppingView
|
|
47
|
+
<EventShoppingView setIsModalOpen={props.setIsModalOpen} onAction={props.onAction} event={event} eventIndex={eventIndex} />
|
|
52
48
|
</View>
|
|
53
49
|
)
|
|
54
50
|
})
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import EventClickComponent from "./EventClickComponent";
|
|
1
|
+
import React, { useState, useEffect, lazy } from 'react';
|
|
2
|
+
|
|
4
3
|
import { WHATMORE_BACKEND_BASE_URL } from '../constants/AppGlobalVars';
|
|
5
4
|
import { extractEvents, removeInvalidEvents } from '../utils/EventSanityUtils';
|
|
6
5
|
import { View } from 'react-native';
|
|
7
6
|
|
|
7
|
+
const EventTileWithProduct = lazy(() => import('./carousel-view/EventTileWithProduct.js'));
|
|
8
|
+
const EventClickComponent = lazy(() => import('./EventClickComponent'));
|
|
9
|
+
|
|
8
10
|
const logEventData = false;
|
|
9
11
|
|
|
10
12
|
function logResponse(data, response = '200'){
|
|
@@ -30,10 +32,12 @@ function transformEventData(data, brandId){
|
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export default function WhatmoreRootComponent(props) {
|
|
35
|
+
var brandId = props.shopId;
|
|
33
36
|
const [data, setData] = useState();
|
|
34
37
|
const [error, setError] = useState();
|
|
38
|
+
const [isModalOpen, setIsModalOpen] = useState(brandId !== '27358003275');
|
|
39
|
+
const [initialEventIndex, setInitialEventIndex] = useState(0)
|
|
35
40
|
|
|
36
|
-
var brandId = props.shopId;
|
|
37
41
|
var eventStatuses = "live,upcoming";
|
|
38
42
|
var isActive = "true";
|
|
39
43
|
|
|
@@ -50,9 +54,9 @@ export default function WhatmoreRootComponent(props) {
|
|
|
50
54
|
+ '&is_active=' + isActive.toString();
|
|
51
55
|
fetch(url)
|
|
52
56
|
.then((response) => response.json())
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
// .then((data) => {
|
|
58
|
+
// return extractEvents(data, false);
|
|
59
|
+
// })
|
|
56
60
|
.then((data) => {
|
|
57
61
|
logEventData && console.log("initial received events size : " + data.length);
|
|
58
62
|
return removeInvalidEvents(data, brandId);
|
|
@@ -79,11 +83,14 @@ export default function WhatmoreRootComponent(props) {
|
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
logEventData && logResponse(data);
|
|
82
|
-
transformEventData(data, brandId);
|
|
86
|
+
// transformEventData(data, brandId);
|
|
83
87
|
logEventData && console.log("final transformed events data : " + JSON.stringify(data));
|
|
84
88
|
logEventData && console.log("valid events size : " + data.length);
|
|
85
89
|
|
|
86
90
|
return (
|
|
87
|
-
|
|
91
|
+
<>
|
|
92
|
+
{brandId == '27358003275' && <EventTileWithProduct isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} events={data} setInitialEventIndex={setInitialEventIndex} />}
|
|
93
|
+
{(isModalOpen || brandId !== '27358003275') && <EventClickComponent isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} events={data} initialEventIndex={initialEventIndex} onAction={props.onAction} /> }
|
|
94
|
+
</>
|
|
88
95
|
);
|
|
89
96
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Text, TouchableOpacity, View, StyleSheet, SafeAreaView, Dimensions } from "react-native";
|
|
3
|
+
import { getGlobalState } from '../../globals/useAppState_APP';
|
|
4
|
+
import Video from 'react-native-video';
|
|
5
|
+
import { useState, useEffect } from 'react';
|
|
6
|
+
import Carousel from 'react-native-snap-carousel'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export default function EventTileWithProduct(props) {
|
|
10
|
+
|
|
11
|
+
const events = props.events;
|
|
12
|
+
const [renderedEvents, setRenderedEvents] = useState(6);
|
|
13
|
+
const isCarousel = React.useRef(null)
|
|
14
|
+
const videoRef = React.useRef(null);
|
|
15
|
+
|
|
16
|
+
const { width, height } = Dimensions.get('window');
|
|
17
|
+
const SLIDER_WIDTH = width + 75;
|
|
18
|
+
const ITEM_WIDTH = Math.round(SLIDER_WIDTH * 0.3)
|
|
19
|
+
const CARD_HEIGHT = height * 0.2;
|
|
20
|
+
const styles = StyleSheet.create({
|
|
21
|
+
cardContainer: {
|
|
22
|
+
borderRadius: 30,
|
|
23
|
+
width: ITEM_WIDTH*0.7,
|
|
24
|
+
height: CARD_HEIGHT,
|
|
25
|
+
position: 'absolute',
|
|
26
|
+
borderRadius: 30,
|
|
27
|
+
elevation: 3,
|
|
28
|
+
|
|
29
|
+
top: 40,
|
|
30
|
+
transform: [{ scale: 1.3 }],
|
|
31
|
+
|
|
32
|
+
},
|
|
33
|
+
video: {
|
|
34
|
+
width: '100%',
|
|
35
|
+
height: '100%',
|
|
36
|
+
borderRadius: 10,
|
|
37
|
+
elevation: 8
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// const [currentIndex, setCurrentIndex] = useState(1);
|
|
42
|
+
|
|
43
|
+
// const handleVideoLoad = (index) => {
|
|
44
|
+
// if (index !== currentIndex && videoRef.current) {
|
|
45
|
+
// videoRef.current.setNativeProps({ paused: false });
|
|
46
|
+
|
|
47
|
+
// }
|
|
48
|
+
// };
|
|
49
|
+
const CarouselCardItem = ({ item, index }) => {
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<TouchableOpacity onPress={()=>handleClick(props, index)} key={index}>
|
|
53
|
+
<View style={styles.cardContainer}>
|
|
54
|
+
<Video
|
|
55
|
+
ref={videoRef}
|
|
56
|
+
|
|
57
|
+
source={{ uri: item?.thumbnail_image }}
|
|
58
|
+
controls={false}
|
|
59
|
+
repeat
|
|
60
|
+
muted
|
|
61
|
+
style={styles.video}
|
|
62
|
+
// paused={!isFocused}
|
|
63
|
+
// onLoad={() => handleVideoLoad(index)}
|
|
64
|
+
/>
|
|
65
|
+
</View>
|
|
66
|
+
</TouchableOpacity>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function handleClick(props, index) {
|
|
71
|
+
console.log('hello', index)
|
|
72
|
+
props.setInitialEventIndex(index);
|
|
73
|
+
props.setIsModalOpen(true);
|
|
74
|
+
}
|
|
75
|
+
function handleSnapToItem(index) {
|
|
76
|
+
setRenderedEvents(prev => prev+1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<SafeAreaView style={{
|
|
81
|
+
width: '100%',
|
|
82
|
+
height: '100%',
|
|
83
|
+
}}>
|
|
84
|
+
<Carousel
|
|
85
|
+
layout="default"
|
|
86
|
+
ref={isCarousel}
|
|
87
|
+
data={events.slice(0,renderedEvents)}
|
|
88
|
+
renderItem={CarouselCardItem}
|
|
89
|
+
sliderWidth={SLIDER_WIDTH}
|
|
90
|
+
itemWidth={ITEM_WIDTH}
|
|
91
|
+
inactiveSlideShift={-15}
|
|
92
|
+
firstItem={1}
|
|
93
|
+
useScrollView={true}
|
|
94
|
+
onSnapToItem={handleSnapToItem}
|
|
95
|
+
/>
|
|
96
|
+
</SafeAreaView>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
@@ -5,23 +5,23 @@ function ShopNow(props){
|
|
|
5
5
|
const whatmorePrimaryColor = getGlobalState('whatmorePrimaryColor');
|
|
6
6
|
const whatmorePrimaryFont = getGlobalState('whatmorePrimaryFont');
|
|
7
7
|
|
|
8
|
-
const onClick = props.onClick;
|
|
8
|
+
// const onClick = props.onClick;
|
|
9
9
|
const height = props.height;
|
|
10
10
|
|
|
11
11
|
const BOX_PADDING = 2;
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
|
-
<
|
|
14
|
+
<View
|
|
15
15
|
style={{
|
|
16
16
|
width: '100%',
|
|
17
17
|
height: height,
|
|
18
18
|
padding: BOX_PADDING,
|
|
19
19
|
backgroundColor: whatmorePrimaryColor
|
|
20
20
|
}}
|
|
21
|
-
onPress={(e) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}}
|
|
21
|
+
// onPress={(e) => {
|
|
22
|
+
// e.stopPropagation();
|
|
23
|
+
// // onClick();
|
|
24
|
+
// }}
|
|
25
25
|
>
|
|
26
26
|
<View
|
|
27
27
|
style={{
|
|
@@ -43,7 +43,7 @@ function ShopNow(props){
|
|
|
43
43
|
{"SHOP NOW"}
|
|
44
44
|
</Text>
|
|
45
45
|
</View>
|
|
46
|
-
</
|
|
46
|
+
</View>
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -7,12 +7,15 @@ import { View, Dimensions, TouchableWithoutFeedback } from 'react-native';
|
|
|
7
7
|
import useAddToCartStates from '../../hooks/useAddToCartStates.js';
|
|
8
8
|
import * as Animatable from 'react-native-animatable';
|
|
9
9
|
import ShopNow from '../cta-buttons/ShopNowButton.jsx';
|
|
10
|
+
import { navigateToProductPage } from '../../api/navigation-commands/NavigationCommands.js';
|
|
10
11
|
|
|
11
12
|
export default function ProductTileV1(props) {
|
|
12
13
|
const event = props.event;
|
|
13
14
|
const product = props.product;
|
|
14
15
|
const [tileTapAnimate, setTileTapAnimate] = useState(false);
|
|
15
16
|
const whatmorePrimaryFont = getGlobalState('whatmorePrimaryFont');
|
|
17
|
+
const brandDomainContext = getGlobalState('brandDomainContext');
|
|
18
|
+
const whatmoreShopId = getGlobalState('whatmoreShopId');
|
|
16
19
|
const PRODUCT_TILE_TOTAL_HEIGHT = Dimensions.get('window').height * 0.2;
|
|
17
20
|
const BASE_FONT_SIZE = 20;
|
|
18
21
|
|
|
@@ -24,23 +27,11 @@ export default function ProductTileV1(props) {
|
|
|
24
27
|
}
|
|
25
28
|
}, [tileTapAnimate]);
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
function handleClick(){
|
|
29
|
-
console.log('click')
|
|
30
|
-
props.setModalVisible(false);
|
|
31
|
-
props.onAction({
|
|
32
|
-
action: "OPEN_PRODUCT",
|
|
33
|
-
params:{
|
|
34
|
-
productId: 'gid://shopify/Product/' + product.client_product_id
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
30
|
return (
|
|
39
31
|
<TouchableWithoutFeedback
|
|
40
32
|
onPress={() => {
|
|
41
33
|
setTileTapAnimate(true);
|
|
42
|
-
|
|
43
|
-
handleClick();
|
|
34
|
+
navigateToProductPage(product, brandDomainContext, whatmoreShopId, props);
|
|
44
35
|
}}
|
|
45
36
|
>
|
|
46
37
|
<Animatable.View
|
|
@@ -139,7 +130,6 @@ export default function ProductTileV1(props) {
|
|
|
139
130
|
<View style={{ flexDirection: 'row', width: '100%', justifyContent: 'center', alignItems: 'center'}}>
|
|
140
131
|
<ShopNow
|
|
141
132
|
height={PRODUCT_TILE_TOTAL_HEIGHT * 0.3}
|
|
142
|
-
onClick={handleClick}
|
|
143
133
|
fontSize={BASE_FONT_SIZE*1.1}
|
|
144
134
|
/>
|
|
145
135
|
</View>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import Svg, {Line} from 'react-native-svg';
|
|
3
|
+
|
|
4
|
+
function CrossIcon({size = 24, color = 'white' }) {
|
|
5
|
+
return (
|
|
6
|
+
<Svg height={size} width={size} viewBox="0 0 24 24">
|
|
7
|
+
<Line x1="1" y1="1" x2="23" y2="23" stroke={color} strokeWidth="2" />
|
|
8
|
+
<Line x1="23" y1="1" x2="1" y2="23" stroke={color} strokeWidth="2" />
|
|
9
|
+
</Svg>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default CrossIcon;
|