@nuskin/routine-feature 1.0.1 → 2.0.1
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/RoutineDetails.js +328 -0
- package/lib/commonjs/RoutineDetails.js.map +1 -0
- package/lib/commonjs/helpers/Accessibility.js +17 -0
- package/lib/commonjs/helpers/Accessibility.js.map +1 -0
- package/lib/commonjs/index.js +227 -153
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/RoutineDetails.js +320 -0
- package/lib/module/RoutineDetails.js.map +1 -0
- package/lib/module/helpers/Accessibility.js +11 -0
- package/lib/module/helpers/Accessibility.js.map +1 -0
- package/lib/module/index.js +227 -148
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/RoutineDetails.d.ts +3 -0
- package/lib/typescript/helpers/Accessibility.d.ts +9 -0
- package/lib/typescript/index.d.ts +3 -5
- package/package.json +17 -10
- package/src/RoutineDetails.tsx +363 -0
- package/src/helpers/Accessibility.tsx +7 -0
- package/src/index.tsx +239 -141
package/src/index.tsx
CHANGED
|
@@ -1,166 +1,217 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
FlatList,
|
|
4
4
|
Image,
|
|
5
5
|
SafeAreaView,
|
|
6
|
-
SectionList,
|
|
7
6
|
StyleSheet,
|
|
8
7
|
Text,
|
|
9
8
|
TouchableOpacity,
|
|
10
9
|
View,
|
|
10
|
+
ActivityIndicator,
|
|
11
11
|
} from 'react-native';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
key: '2',
|
|
29
|
-
text: 'Card Title 2',
|
|
30
|
-
uri: 'https://picsum.photos/id/10/200',
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
key: '3',
|
|
35
|
-
text: 'Card Title 3',
|
|
36
|
-
uri: 'https://picsum.photos/id/1002/200',
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
title: 'Featured Routines',
|
|
42
|
-
horizontal: true,
|
|
43
|
-
data: [
|
|
44
|
-
{
|
|
45
|
-
key: '1',
|
|
46
|
-
text: 'Card Title 1',
|
|
47
|
-
uri: 'https://picsum.photos/id/1011/200',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
key: '2',
|
|
51
|
-
text: 'Card Title 2',
|
|
52
|
-
uri: 'https://picsum.photos/id/1012/200',
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
key: '3',
|
|
57
|
-
text: 'Card Title 3',
|
|
58
|
-
uri: 'https://picsum.photos/id/1013/200',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
title: 'Suggested Routines',
|
|
64
|
-
horizontal: true,
|
|
65
|
-
data: [
|
|
66
|
-
{
|
|
67
|
-
key: '1',
|
|
68
|
-
text: 'Card Title 1',
|
|
69
|
-
uri: 'https://picsum.photos/id/1020/200',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
key: '2',
|
|
73
|
-
text: 'Card Title 2',
|
|
74
|
-
uri: 'https://picsum.photos/id/1024/200',
|
|
75
|
-
},
|
|
12
|
+
import { gql, useQuery } from '@apollo/client';
|
|
13
|
+
import { useNavigation } from '@react-navigation/native';
|
|
14
|
+
import {
|
|
15
|
+
VeraHeader,
|
|
16
|
+
Logo,
|
|
17
|
+
HeaderCart,
|
|
18
|
+
colors,
|
|
19
|
+
ErrorScreen,
|
|
20
|
+
} from '@ns/mobile-ui';
|
|
21
|
+
import { localization, localizationState } from '@nuskin/utils-module';
|
|
22
|
+
import { useSnapshot } from 'valtio';
|
|
23
|
+
import RoutineDetails from './RoutineDetails';
|
|
24
|
+
import { Logger } from '@nuskin/mobile-logging';
|
|
25
|
+
import { accessibility } from './helpers/Accessibility';
|
|
26
|
+
import { createStackNavigator } from '@react-navigation/stack';
|
|
76
27
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
28
|
+
const Stack = createStackNavigator();
|
|
29
|
+
export const FETCH_ROUTINES_PAGE = gql`
|
|
30
|
+
query fetchAllHomePages($locale: String) {
|
|
31
|
+
result: all_routine(fallback_locale: true, locale: $locale) {
|
|
32
|
+
items {
|
|
33
|
+
products_used_label
|
|
34
|
+
sort_list_label
|
|
35
|
+
title
|
|
36
|
+
routines {
|
|
37
|
+
products {
|
|
38
|
+
product_name
|
|
39
|
+
product_category
|
|
40
|
+
product_imageConnection {
|
|
41
|
+
edges {
|
|
42
|
+
node {
|
|
43
|
+
url
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
products_used_label
|
|
49
|
+
routine_title
|
|
50
|
+
routine_subtitle
|
|
51
|
+
routines_description
|
|
52
|
+
routine_step_label
|
|
53
|
+
reference
|
|
54
|
+
routine_imageConnection {
|
|
55
|
+
edges {
|
|
56
|
+
node {
|
|
57
|
+
url
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
steps {
|
|
62
|
+
imageConnection {
|
|
63
|
+
edges {
|
|
64
|
+
node {
|
|
65
|
+
url
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
step_sub_description
|
|
70
|
+
step_title
|
|
71
|
+
step_description
|
|
72
|
+
style
|
|
73
|
+
image_title
|
|
74
|
+
image_description
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
85
81
|
|
|
86
82
|
const ListItem = ({ item, index }) => {
|
|
83
|
+
const navigation = useNavigation();
|
|
84
|
+
const handleOnPress = () => {
|
|
85
|
+
navigation.navigate('RoutineDetails' as never, item as never);
|
|
86
|
+
};
|
|
87
87
|
return (
|
|
88
|
-
<View style={
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
<View style={styles.itemContainer}>
|
|
89
|
+
<TouchableOpacity onPress={handleOnPress}>
|
|
90
|
+
<View>
|
|
91
|
+
<Image
|
|
92
|
+
{...accessibility(`list-item-${index}`)}
|
|
93
|
+
source={{
|
|
94
|
+
uri: item.routine_imageConnection?.edges[0]?.node?.url,
|
|
95
|
+
}}
|
|
96
|
+
style={styles.itemPhoto}
|
|
97
|
+
/>
|
|
98
|
+
</View>
|
|
99
|
+
<View style={styles.itemTextContainer}>
|
|
100
|
+
<View style={styles.itemTitleContainer}>
|
|
101
|
+
<Text
|
|
102
|
+
{...accessibility(`list-item-title-${index}`)}
|
|
103
|
+
style={styles.itemTextTitle}
|
|
104
|
+
>
|
|
105
|
+
{item.routine_title}
|
|
106
|
+
</Text>
|
|
107
|
+
<Text style={styles.itemTextSteps}>
|
|
108
|
+
{item.steps.length} {item.routine_step_label}
|
|
109
|
+
</Text>
|
|
110
|
+
</View>
|
|
111
|
+
<View style={styles.listContainer}>
|
|
112
|
+
<Text style={styles.itemText}>{item.products_used_label}</Text>
|
|
113
|
+
<FlatList
|
|
114
|
+
data={item.products}
|
|
115
|
+
horizontal
|
|
116
|
+
renderItem={({ item, index }) => (
|
|
117
|
+
<Image
|
|
118
|
+
key={index}
|
|
119
|
+
{...accessibility(`list-item-product-${index}`)}
|
|
120
|
+
source={{
|
|
121
|
+
uri: item.product_imageConnection?.edges[0]?.node?.url,
|
|
122
|
+
}}
|
|
123
|
+
style={styles.productPhoto}
|
|
124
|
+
resizeMode="contain"
|
|
125
|
+
/>
|
|
126
|
+
)}
|
|
127
|
+
showsHorizontalScrollIndicator={false}
|
|
128
|
+
/>
|
|
129
|
+
</View>
|
|
130
|
+
</View>
|
|
131
|
+
</TouchableOpacity>
|
|
97
132
|
</View>
|
|
98
133
|
);
|
|
99
134
|
};
|
|
100
135
|
|
|
101
136
|
const Routines = () => {
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
137
|
+
const localizationStore = useSnapshot(localizationState);
|
|
138
|
+
const [refresh, setRefresh] = useState(false);
|
|
139
|
+
const locale = localization.getLocalization(
|
|
140
|
+
localization.LocalizationFormat.CONTENT_STACK
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const { loading, error, data, refetch } = useQuery(FETCH_ROUTINES_PAGE, {
|
|
144
|
+
variables: { locale },
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
setRefresh(!refresh);
|
|
149
|
+
}, [localizationStore]);
|
|
150
|
+
|
|
151
|
+
const routinesPageData = data ? data.result.items[0] : {};
|
|
152
|
+
if (error || !routinesPageData) {
|
|
153
|
+
const errorCode = error?.graphQLErrors[0]?.extensions?.errors[0]?.code;
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<SafeAreaView style={styles.container}>
|
|
157
|
+
<ErrorScreen errorCode={errorCode} refresh={() => refetch()} />
|
|
158
|
+
</SafeAreaView>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (loading) {
|
|
162
|
+
return (
|
|
163
|
+
<SafeAreaView
|
|
164
|
+
style={styles.container}
|
|
165
|
+
{...accessibility('routine-container-loading')}
|
|
166
|
+
>
|
|
167
|
+
<ActivityIndicator
|
|
168
|
+
size="large"
|
|
169
|
+
{...accessibility('routine-activity-indicator')}
|
|
170
|
+
/>
|
|
171
|
+
</SafeAreaView>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
105
174
|
|
|
106
175
|
return (
|
|
107
176
|
<SafeAreaView style={styles.container} testID="routineStack">
|
|
108
177
|
<VeraHeader
|
|
109
178
|
left={<Logo accessibilityLabel="logo" />}
|
|
110
179
|
right={<HeaderCart accessibilityLabel="crt-btn" />}
|
|
111
|
-
title=
|
|
112
|
-
|
|
180
|
+
title={routinesPageData.title}
|
|
181
|
+
{...accessibility('routine-activity-indicator')}
|
|
113
182
|
/>
|
|
114
|
-
<View style={
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
contentContainerStyle={{ paddingHorizontal: 15 }}
|
|
131
|
-
/>
|
|
132
|
-
</>
|
|
133
|
-
)}
|
|
134
|
-
renderItem={({ item, section, index }) => {
|
|
135
|
-
if (section.horizontal) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
return <ListItem item={item} index={index} />;
|
|
139
|
-
}}
|
|
140
|
-
/>
|
|
183
|
+
<View style={styles.routinesContainer}>
|
|
184
|
+
{routinesPageData && (
|
|
185
|
+
<>
|
|
186
|
+
<Text style={styles.sortListText}>
|
|
187
|
+
{routinesPageData.sort_list_label}
|
|
188
|
+
</Text>
|
|
189
|
+
<FlatList
|
|
190
|
+
data={routinesPageData.routines}
|
|
191
|
+
renderItem={({ item, index }) => (
|
|
192
|
+
<ListItem index={index} item={item} key={index} />
|
|
193
|
+
)}
|
|
194
|
+
showsHorizontalScrollIndicator={false}
|
|
195
|
+
contentContainerStyle={{ paddingHorizontal: 15 }}
|
|
196
|
+
/>
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
141
199
|
</View>
|
|
142
200
|
</SafeAreaView>
|
|
143
201
|
);
|
|
144
202
|
};
|
|
145
203
|
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
|
149
|
-
<Text>Routine</Text>
|
|
150
|
-
</View>
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function RoutineStack(LOG, { navigation }) {
|
|
204
|
+
function RoutineStack() {
|
|
205
|
+
const navigation = useNavigation();
|
|
155
206
|
useEffect(() => {
|
|
156
207
|
const unsubscribe = navigation.addListener('focus', () => {
|
|
157
|
-
|
|
208
|
+
Logger.info('User navigated to the RoutineStack page.');
|
|
158
209
|
});
|
|
159
210
|
return unsubscribe;
|
|
160
211
|
}, [navigation]);
|
|
161
212
|
|
|
162
213
|
return (
|
|
163
|
-
<Stack.Navigator>
|
|
214
|
+
<Stack.Navigator initialRouteName="Routines">
|
|
164
215
|
<Stack.Screen
|
|
165
216
|
name="Routines"
|
|
166
217
|
component={Routines}
|
|
@@ -175,20 +226,25 @@ function RoutineStack(LOG, { navigation }) {
|
|
|
175
226
|
);
|
|
176
227
|
}
|
|
177
228
|
|
|
178
|
-
function useRoutine() {
|
|
179
|
-
//
|
|
180
|
-
}
|
|
181
|
-
|
|
182
229
|
const styles = StyleSheet.create({
|
|
183
230
|
container: {
|
|
184
231
|
flex: 1,
|
|
185
|
-
backgroundColor:
|
|
232
|
+
backgroundColor: colors.white,
|
|
233
|
+
},
|
|
234
|
+
routinesContainer: {
|
|
235
|
+
backgroundColor: colors.primaryGray,
|
|
236
|
+
flex: 1,
|
|
237
|
+
paddingTop: 10,
|
|
238
|
+
},
|
|
239
|
+
listContainer: {
|
|
240
|
+
flexDirection: 'column',
|
|
241
|
+
paddingHorizontal: 15,
|
|
242
|
+
paddingVertical: 10,
|
|
186
243
|
},
|
|
187
244
|
sectionHeader: {
|
|
188
245
|
textTransform: 'uppercase',
|
|
189
246
|
fontWeight: '600',
|
|
190
247
|
fontSize: 14,
|
|
191
|
-
// color: '#f4f4f4',
|
|
192
248
|
marginTop: 20,
|
|
193
249
|
paddingHorizontal: 15,
|
|
194
250
|
marginBottom: 5,
|
|
@@ -197,19 +253,61 @@ const styles = StyleSheet.create({
|
|
|
197
253
|
margin: 10,
|
|
198
254
|
borderRadius: 14,
|
|
199
255
|
},
|
|
256
|
+
itemContainer: {
|
|
257
|
+
backgroundColor: 'transparent',
|
|
258
|
+
flex: 1,
|
|
259
|
+
marginBottom: 10,
|
|
260
|
+
},
|
|
261
|
+
itemTextContainer: {
|
|
262
|
+
backgroundColor: colors.white,
|
|
263
|
+
paddingTop: 20,
|
|
264
|
+
paddingBottom: 10,
|
|
265
|
+
},
|
|
200
266
|
itemPhoto: {
|
|
201
|
-
width:
|
|
202
|
-
|
|
203
|
-
|
|
267
|
+
width: '100%',
|
|
268
|
+
minHeight: 160,
|
|
269
|
+
},
|
|
270
|
+
productPhoto: {
|
|
271
|
+
margin: 2,
|
|
272
|
+
width: 40,
|
|
273
|
+
height: 40,
|
|
274
|
+
borderRadius: 50,
|
|
275
|
+
borderColor: '#EDEDED',
|
|
276
|
+
borderWidth: 1,
|
|
277
|
+
},
|
|
278
|
+
itemTitleContainer: {
|
|
279
|
+
flexDirection: 'row',
|
|
280
|
+
justifyContent: 'space-between',
|
|
281
|
+
paddingHorizontal: 15,
|
|
282
|
+
},
|
|
283
|
+
itemTextTitle: {
|
|
284
|
+
color: colors.primaryBlack,
|
|
285
|
+
fontWeight: '600',
|
|
286
|
+
fontSize: 18,
|
|
204
287
|
},
|
|
205
288
|
itemText: {
|
|
206
|
-
color:
|
|
289
|
+
color: colors.primaryBlack,
|
|
207
290
|
fontWeight: 'bold',
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
291
|
+
fontSize: 12,
|
|
292
|
+
letterSpacing: 0.05,
|
|
293
|
+
paddingBottom: 5,
|
|
294
|
+
textTransform: 'uppercase',
|
|
295
|
+
},
|
|
296
|
+
itemTextSteps: {
|
|
297
|
+
color: colors.primaryBlack,
|
|
298
|
+
fontWeight: 'bold',
|
|
299
|
+
textTransform: 'uppercase',
|
|
300
|
+
},
|
|
301
|
+
sortListText: {
|
|
302
|
+
color: colors.primaryBlack,
|
|
303
|
+
fontWeight: 'bold',
|
|
304
|
+
textTransform: 'uppercase',
|
|
305
|
+
textAlign: 'right',
|
|
306
|
+
marginRight: 10,
|
|
307
|
+
letterSpacing: 0.5,
|
|
308
|
+
paddingVertical: 10,
|
|
309
|
+
paddingRight: 20,
|
|
212
310
|
},
|
|
213
311
|
});
|
|
214
312
|
|
|
215
|
-
export { RoutineStack
|
|
313
|
+
export { RoutineStack };
|