@nuskin/routine-feature 1.0.0 → 2.0.0

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/src/index.tsx CHANGED
@@ -1,160 +1,201 @@
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 { createNativeStackNavigator } from '@nuskin/mobile-navigation';
13
- import { VeraHeader, Logo, HeaderCart } from '@ns/mobile-ui';
14
-
15
- const Stack = createNativeStackNavigator();
16
-
17
- const SECTIONS = [
18
- {
19
- title: 'My Routines',
20
- horizontal: true,
21
- data: [
22
- {
23
- key: '1',
24
- text: 'Card Title Onessssss',
25
- uri: 'https://picsum.photos/id/1/200',
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
- key: '3',
79
- text: 'Card Title 3',
80
- uri: 'https://picsum.photos/id/1027/200',
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
+ routines_description
51
+ routine_step_label
52
+ routine_imageConnection {
53
+ edges {
54
+ node {
55
+ url
56
+ }
57
+ }
58
+ }
59
+ steps {
60
+ imageConnection {
61
+ edges {
62
+ node {
63
+ url
64
+ }
65
+ }
66
+ }
67
+ step_sub_description
68
+ step_title
69
+ step_description
70
+ style
71
+ image_title
72
+ image_description
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ `;
85
79
 
86
- const ListItem = ({ item, index }) => {
80
+ const ListItem = ({ item }) => {
81
+ const navigation = useNavigation();
82
+ const handleOnPress = () => {
83
+ navigation.navigate('RoutineDetails' as never, item as never);
84
+ };
87
85
  return (
88
- <View style={[styles.item, index === 0 ? { marginLeft: 0 } : {}]}>
89
- <Image
90
- source={{
91
- uri: item.uri,
92
- }}
93
- style={styles.itemPhoto}
94
- resizeMode="cover"
95
- />
96
- <Text style={styles.itemText}>{item.text}</Text>
86
+ <View style={styles.itemContainer}>
87
+ <TouchableOpacity onPress={handleOnPress}>
88
+ <View>
89
+ <Image
90
+ source={{
91
+ uri: item.routine_imageConnection?.edges[0]?.node?.url,
92
+ }}
93
+ style={styles.itemPhoto}
94
+ />
95
+ </View>
96
+ <View style={styles.itemTextContainer}>
97
+ <View style={styles.itemTitleContainer}>
98
+ <Text style={styles.itemTextTitle}>{item.routine_title}</Text>
99
+ <Text style={styles.itemTextSteps}>
100
+ {item.steps.length} {item.routine_step_label}
101
+ </Text>
102
+ </View>
103
+ <View style={styles.listContainer}>
104
+ <Text style={styles.itemText}>{item.products_used_label}</Text>
105
+ <FlatList
106
+ data={item.products}
107
+ horizontal
108
+ renderItem={({ item, index }) => (
109
+ <Image
110
+ key={index}
111
+ source={{
112
+ uri: item.product_imageConnection?.edges[0]?.node?.url,
113
+ }}
114
+ style={styles.productPhoto}
115
+ resizeMode="contain"
116
+ />
117
+ )}
118
+ showsHorizontalScrollIndicator={false}
119
+ />
120
+ </View>
121
+ </View>
122
+ </TouchableOpacity>
97
123
  </View>
98
124
  );
99
125
  };
100
126
 
101
127
  const Routines = () => {
102
- const handleOnPress = () => {
103
- // console.log('onPress', section)
104
- };
128
+ const localizationStore = useSnapshot(localizationState);
129
+ const [refresh, setRefresh] = useState(false);
130
+ const locale = localization.getLocalization(
131
+ localization.LocalizationFormat.CONTENT_STACK
132
+ );
133
+
134
+ const { loading, error, data, refetch } = useQuery(FETCH_ROUTINES_PAGE, {
135
+ variables: { locale },
136
+ });
137
+
138
+ useEffect(() => {
139
+ setRefresh(!refresh);
140
+ }, [localizationStore]);
141
+
142
+ const routinesPageData = data ? data.result.items[0] : {};
143
+ if (error || !routinesPageData) {
144
+ const errorCode = error?.graphQLErrors[0]?.extensions?.errors[0]?.code;
145
+
146
+ return (
147
+ <SafeAreaView style={styles.container}>
148
+ <ErrorScreen errorCode={errorCode} refresh={() => refetch()} />
149
+ </SafeAreaView>
150
+ );
151
+ }
152
+ if (loading) {
153
+ return (
154
+ <SafeAreaView
155
+ style={styles.container}
156
+ {...accessibility('routine-container-loading')}
157
+ >
158
+ <ActivityIndicator
159
+ size="large"
160
+ {...accessibility('routine-activity-indicator')}
161
+ />
162
+ </SafeAreaView>
163
+ );
164
+ }
105
165
 
106
166
  return (
107
167
  <SafeAreaView style={styles.container} testID="routineStack">
108
168
  <VeraHeader
109
169
  left={<Logo accessibilityLabel="logo" />}
110
170
  right={<HeaderCart accessibilityLabel="crt-btn" />}
111
- title="Routines"
112
- accessibilityLabel="header"
171
+ title={routinesPageData.title}
172
+ {...accessibility('routine-activity-indicator')}
113
173
  />
114
- <View style={{ flex: 1, backgroundColor: 'white' }}>
115
- <SectionList
116
- stickySectionHeadersEnabled={false}
117
- sections={SECTIONS}
118
- renderSectionHeader={({ section }) => (
119
- <>
120
- <Text style={styles.sectionHeader}>{section.title}</Text>
121
- <FlatList
122
- horizontal
123
- data={section.data}
124
- renderItem={({ item, index }) => (
125
- <TouchableOpacity onPress={handleOnPress}>
126
- <ListItem item={item} index={index} />
127
- </TouchableOpacity>
128
- )}
129
- showsHorizontalScrollIndicator={false}
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
- />
174
+ <View style={styles.routinesContainer}>
175
+ {routinesPageData && (
176
+ <>
177
+ <Text style={styles.sortListText}>
178
+ {routinesPageData.sort_list_label}
179
+ </Text>
180
+ <FlatList
181
+ data={routinesPageData.routines}
182
+ renderItem={({ item, index }) => (
183
+ <ListItem item={item} key={index} />
184
+ )}
185
+ showsHorizontalScrollIndicator={false}
186
+ contentContainerStyle={{ paddingHorizontal: 15 }}
187
+ />
188
+ </>
189
+ )}
141
190
  </View>
142
191
  </SafeAreaView>
143
192
  );
144
193
  };
145
194
 
146
- function RoutineDetails() {
147
- return (
148
- <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
149
- <Text>Routine</Text>
150
- </View>
151
- );
152
- }
153
-
154
- function RoutineStack(LOG, { navigation }) {
195
+ function RoutineStack({ navigation }) {
155
196
  useEffect(() => {
156
197
  const unsubscribe = navigation.addListener('focus', () => {
157
- LOG.info('User navigated to the RoutineStack page.');
198
+ Logger.info('User navigated to the RoutineStack page.');
158
199
  });
159
200
  return unsubscribe;
160
201
  }, [navigation]);
@@ -175,20 +216,25 @@ function RoutineStack(LOG, { navigation }) {
175
216
  );
176
217
  }
177
218
 
178
- function useRoutine() {
179
- //
180
- }
181
-
182
219
  const styles = StyleSheet.create({
183
220
  container: {
184
221
  flex: 1,
185
- backgroundColor: '#F9F9F9',
222
+ backgroundColor: colors.white,
223
+ },
224
+ routinesContainer: {
225
+ backgroundColor: colors.primaryGray,
226
+ flex: 1,
227
+ paddingTop: 10,
228
+ },
229
+ listContainer: {
230
+ flexDirection: 'column',
231
+ paddingHorizontal: 15,
232
+ paddingVertical: 10,
186
233
  },
187
234
  sectionHeader: {
188
235
  textTransform: 'uppercase',
189
236
  fontWeight: '600',
190
237
  fontSize: 14,
191
- // color: '#f4f4f4',
192
238
  marginTop: 20,
193
239
  paddingHorizontal: 15,
194
240
  marginBottom: 5,
@@ -197,19 +243,62 @@ const styles = StyleSheet.create({
197
243
  margin: 10,
198
244
  borderRadius: 14,
199
245
  },
246
+ itemContainer: {
247
+ backgroundColor: 'transparent',
248
+ flex: 1,
249
+ marginBottom: 10,
250
+ },
251
+ itemTextContainer: {
252
+ backgroundColor: colors.white,
253
+ paddingTop: 20,
254
+ paddingBottom: 10,
255
+ },
200
256
  itemPhoto: {
201
- width: 230,
202
- height: 160,
203
- borderRadius: 14,
257
+ width: '100%',
258
+ minHeight: 160,
259
+ },
260
+ productPhoto: {
261
+ margin: 2,
262
+ width: 40,
263
+ height: 40,
264
+ borderRadius: 50,
265
+ borderColor: '#EDEDED',
266
+ borderStyle: 'solid',
267
+ borderWidth: 1,
268
+ },
269
+ itemTitleContainer: {
270
+ flexDirection: 'row',
271
+ justifyContent: 'space-between',
272
+ paddingHorizontal: 15,
273
+ },
274
+ itemTextTitle: {
275
+ color: colors.primaryBlack,
276
+ fontWeight: '600',
277
+ fontSize: 18,
204
278
  },
205
279
  itemText: {
206
- color: 'rgba(255, 255, 255, 1)',
280
+ color: colors.primaryBlack,
207
281
  fontWeight: 'bold',
208
- marginTop: 5,
209
- position: 'absolute',
210
- left: 16,
211
- bottom: 16,
282
+ fontSize: 12,
283
+ letterSpacing: 0.05,
284
+ paddingBottom: 5,
285
+ textTransform: 'uppercase',
286
+ },
287
+ itemTextSteps: {
288
+ color: colors.primaryBlack,
289
+ fontWeight: 'bold',
290
+ textTransform: 'uppercase',
291
+ },
292
+ sortListText: {
293
+ color: colors.primaryBlack,
294
+ fontWeight: 'bold',
295
+ textTransform: 'uppercase',
296
+ textAlign: 'right',
297
+ marginRight: 10,
298
+ letterSpacing: 0.5,
299
+ paddingVertical: 10,
300
+ paddingRight: 20,
212
301
  },
213
302
  });
214
303
 
215
- export { RoutineStack, useRoutine };
304
+ export { RoutineStack };