ordering-ui-react-native 0.11.11 → 0.11.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.11.11",
3
+ "version": "0.11.15",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -92,6 +92,7 @@
92
92
  "react-native-restart": "^0.0.22",
93
93
  "react-native-safe-area-context": "^3.1.8",
94
94
  "react-native-screens": "^2.11.0",
95
+ "react-native-signature-canvas": "^4.3.0",
95
96
  "react-native-snap-carousel": "^3.9.1",
96
97
  "react-native-swipe-gestures": "^1.0.5",
97
98
  "react-native-vector-icons": "^7.1.0",
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useEffect, useState, useRef } from 'react';
2
2
  import {
3
3
  TouchableOpacity,
4
4
  ActivityIndicator,
@@ -42,6 +42,8 @@ import { OIcon, OIconButton, OText } from '../shared';
42
42
  import { MessagesParams } from '../../types';
43
43
  import { USER_TYPE } from '../../config/constants';
44
44
 
45
+ import SignatureScreen from 'react-native-signature-canvas';
46
+
45
47
  const ChatUI = (props: MessagesParams) => {
46
48
  const {
47
49
  type,
@@ -82,6 +84,8 @@ const ChatUI = (props: MessagesParams) => {
82
84
  : 'Landscape',
83
85
  );
84
86
 
87
+ const [isShowSignaturePad, setIsShowSignaturePad] = useState(false)
88
+
85
89
  // Events
86
90
  Dimensions.addEventListener('change', ({ window: { width, height } }) => {
87
91
  if (width < height) {
@@ -350,6 +354,7 @@ const ChatUI = (props: MessagesParams) => {
350
354
  setImage && setImage(null);
351
355
  setFile && setFile({ ...file, uri: '', type: '', name: '', size: 0 });
352
356
  setMessage && setMessage('');
357
+ setIsShowSignaturePad(false)
353
358
  };
354
359
 
355
360
  const messageConsole = (message: any) => {
@@ -777,6 +782,20 @@ const ChatUI = (props: MessagesParams) => {
777
782
  placeholderTextColor={theme.colors.composerPlaceHolder}
778
783
  />
779
784
 
785
+ <TouchableOpacity
786
+ onPress={() => {
787
+ setImage && setImage(null);
788
+ setIsShowSignaturePad(!isShowSignaturePad);
789
+ }}>
790
+ <MaterialCommunityIcon
791
+ name="pen"
792
+ color={
793
+ isShowSignaturePad ? theme.colors.primary : theme.colors.arrowColor
794
+ }
795
+ size={24}
796
+ />
797
+ </TouchableOpacity>
798
+
780
799
  {!file.type && (
781
800
  <Actions
782
801
  {...props}
@@ -789,7 +808,9 @@ const ChatUI = (props: MessagesParams) => {
789
808
  <OIconButton
790
809
  borderColor={theme.colors.transparent}
791
810
  icon={
792
- image ? { uri: image } : theme.images.general.imageChat
811
+ !isShowSignaturePad && image
812
+ ? { uri: image }
813
+ : theme.images.general.imageChat
793
814
  }
794
815
  iconStyle={{
795
816
  borderRadius: image ? 10 : 0,
@@ -800,7 +821,7 @@ const ChatUI = (props: MessagesParams) => {
800
821
  iconCover
801
822
  />
802
823
 
803
- {image && (
824
+ {image && !isShowSignaturePad && (
804
825
  <TouchableOpacity
805
826
  style={{
806
827
  position: 'absolute',
@@ -1000,6 +1021,80 @@ const ChatUI = (props: MessagesParams) => {
1000
1021
  );
1001
1022
  };
1002
1023
 
1024
+ const imgHeight = 120;
1025
+ const signatureStyle = `
1026
+ .m-signature-pad {
1027
+ box-shadow: none;
1028
+ border: none;
1029
+ }
1030
+ .m-signature-pad--body {
1031
+ border: none;
1032
+ }
1033
+ .m-signature-pad--footer {
1034
+ display: none;
1035
+ margin: 0px;
1036
+ }
1037
+ body,html {
1038
+ height: ${imgHeight}px;
1039
+ border-radius: 7.6px;
1040
+ }
1041
+ .m-signature-pad--footer
1042
+ .button {
1043
+ background-color: red;
1044
+ color: #FFF;
1045
+ }
1046
+ `;
1047
+
1048
+ const signatureRef = useRef<any>();
1049
+
1050
+ const handleClear = () => {
1051
+ setImage && setImage(null);
1052
+ signatureRef.current.clearSignature();
1053
+ };
1054
+
1055
+ const handleEnd = () => {
1056
+ signatureRef.current.readSignature();
1057
+ };
1058
+
1059
+ const handleOK = (signature: any) => {
1060
+ setImage && setImage(signature);
1061
+ };
1062
+
1063
+ const renderChatFooter = () => {
1064
+ return (
1065
+ <View
1066
+ style={{
1067
+ height: imgHeight,
1068
+ paddingHorizontal: 30,
1069
+ paddingVertical: 10,
1070
+ borderTopColor: theme.colors.tabBar,
1071
+ borderTopWidth: 1
1072
+ }}
1073
+ >
1074
+ <SignatureScreen
1075
+ ref={signatureRef}
1076
+ onOK={handleOK}
1077
+ webStyle={signatureStyle}
1078
+ backgroundColor={theme.colors.composerView}
1079
+ onEnd={handleEnd}
1080
+ />
1081
+ <TouchableOpacity
1082
+ style={{
1083
+ position: 'absolute',
1084
+ right: 35,
1085
+ top: 15
1086
+ }}
1087
+ onPress={handleClear}>
1088
+ <MaterialCommunityIcon
1089
+ name="close"
1090
+ color={theme.colors.textGray}
1091
+ size={24}
1092
+ />
1093
+ </TouchableOpacity>
1094
+ </View>
1095
+ )
1096
+ }
1097
+
1003
1098
  return (
1004
1099
  <SafeAreaView style={{ flex: 1 }}>
1005
1100
  <Wrapper>
@@ -1025,6 +1120,7 @@ const ChatUI = (props: MessagesParams) => {
1025
1120
  scrollToBottom
1026
1121
  renderAvatar={renderAvatar}
1027
1122
  showAvatarForEveryMessage={true}
1123
+ renderChatFooter={isShowSignaturePad ? renderChatFooter : undefined}
1028
1124
  renderInputToolbar={renderInputToolbar}
1029
1125
  renderComposer={renderComposer}
1030
1126
  renderSend={renderSend}
@@ -53,6 +53,7 @@ const FloatingButtonUI = (props: FloatingButtonParams) => {
53
53
  return (
54
54
  <Container
55
55
  isIos={Platform.OS === 'ios'}
56
+ paddingBottomIos={props.paddingBottomIos}
56
57
  style={{ paddingHorizontal: props.isPadding ? 30 : 0 }}>
57
58
  <View
58
59
  style={{
@@ -15,7 +15,7 @@ export const Container = styled.View`
15
15
  ${(props: any) =>
16
16
  props.isIos &&
17
17
  css`
18
- padding-bottom: 5px;
18
+ padding-bottom: ${(props: any) => props.paddingBottomIos ? `${props.paddingBottomIos}px` : '5px'};
19
19
  `}
20
20
  `;
21
21
 
@@ -436,6 +436,7 @@ export interface FloatingButtonParams {
436
436
  secondButton?: boolean;
437
437
  firstColorCustom?: string;
438
438
  secondColorCustom?: string;
439
+ paddingBottomIos?: any;
439
440
  }
440
441
  export interface MomentOptionParams {
441
442
  navigation: any;
@@ -6,9 +6,7 @@ import {
6
6
  useOrder,
7
7
  useSession,
8
8
  useConfig,
9
- useApi,
10
- useToast,
11
- ToastType
9
+ useApi
12
10
  } from 'ordering-components/native'
13
11
  import Carousel from 'react-native-snap-carousel';
14
12
  import Geocoder from 'react-native-geocoding';
@@ -28,18 +26,16 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
28
26
 
29
27
  const theme = useTheme();
30
28
  const [, t] = useLanguage();
31
- const [{user, auth, accessToken}] = useSession()
29
+ const [{user, accessToken}] = useSession()
32
30
  const [, {changeAddress}] = useOrder()
33
31
  const [orientationState] = useDeviceOrientation();
34
32
  const [configState] = useConfig()
35
33
  const [ordering] = useApi()
36
- const [, {showToast}] = useToast()
37
34
  const [addressState, setAddressState] = useState<any>({ loading: false, changes: {}, error: null, address: {} })
38
35
  const googleMapsApiKey = configState?.configs?.google_maps_api_key?.value
39
36
 
40
37
  const _categories: any = business?.original?.categories;
41
38
  let _promos: any = [];
42
-
43
39
  _categories?.forEach((categ: any) => {
44
40
  const _featuredProds = categ?.products?.filter(
45
41
  (prod: any) => prod.featured,
@@ -52,7 +48,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
52
48
 
53
49
  const handleCurrentUserLocation = async () => {
54
50
  let addressValue : any = []
55
- const data: any = { address: null, error: null }
51
+ let data: any = { address: null, error: null }
56
52
  const filterAddressInfo = [
57
53
  { tag: 'street_number', isShort: true },
58
54
  { tag: 'route', isShort: true },
@@ -60,13 +56,11 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
60
56
  { tag: 'administrative_area_level_1', isShort: false },
61
57
  { tag: 'country', isShort: false },
62
58
  ]
63
-
64
- try {
65
59
  Geocoder.init(googleMapsApiKey);
66
60
  Geocoder.from({
67
- latitude: business.location.lat,
68
- longitude: business.location.lng
69
- }).then((json : any) => {
61
+ latitude: business.location?.lat,
62
+ longitude: business.location?.lng
63
+ }).then( async (json : any) => {
70
64
  if(json.results && json.results?.length > 0){
71
65
  for (const component of json.results?.[0].address_components) {
72
66
  const addressType = component.types?.[0]
@@ -76,7 +70,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
76
70
  }
77
71
  }
78
72
  }
79
- data.address = {
73
+ data = {
80
74
  address: addressValue.join(', '),
81
75
  location: json.results[0].geometry.location,
82
76
  map_data: {
@@ -84,44 +78,38 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
84
78
  place_id: json.results?.[0].place_id
85
79
  }
86
80
  }
81
+ setAddressState({ ...addressState, loading: true })
82
+ try {
83
+ const { content } = await ordering
84
+ .users(user?.id)
85
+ .addresses()
86
+ .save(data.address, { accessToken })
87
+ setAddressState({
88
+ ...addressState,
89
+ loading: false,
90
+ error: content.error ? content.result : null,
91
+ })
92
+ if (!content.error && data) {
93
+ setAddressState({
94
+ ...addressState,
95
+ address: data
96
+ })
97
+ changeAddress(data)
98
+ }
99
+ } catch (err : any) {
100
+ setAddressState({
101
+ ...addressState,
102
+ loading: false,
103
+ error: [err.message],
104
+ address: {}
105
+ })
106
+ }
87
107
  }
88
108
  })
89
- } catch (err : any){
90
- showToast(ToastType.Error, err?.message)
91
- }
92
- setAddressState({ ...addressState, loading: true })
93
- try {
94
- const { content } = await ordering
95
- .users(user?.id)
96
- .addresses()
97
- .save(data.address, { accessToken })
98
- setAddressState({
99
- ...addressState,
100
- loading: false,
101
- error: content.error ? content.result : null,
102
- })
103
- if (!content.error) {
104
- setAddressState({
105
- ...addressState,
106
- address: content.result
107
- })
108
- changeAddress(content.result.id, {
109
- address: content.result,
110
- isEdit: false
111
- })
112
- }
113
- } catch (err : any) {
114
- setAddressState({
115
- ...addressState,
116
- loading: false,
117
- error: [err.message],
118
- address: {}
119
- })
120
- }
121
109
  }
122
110
 
123
111
  useEffect(() => {
124
- if(business?.location && auth && googleMapsApiKey){
112
+ if(business?.location?.lat && business?.location?.lng){
125
113
  handleCurrentUserLocation()
126
114
  }
127
115
  }, [business?.location, googleMapsApiKey])
@@ -212,7 +200,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
212
200
  );
213
201
 
214
202
  if (businessState?.error || addressState.error) {
215
- return <OText>error!</OText>;
203
+ return <OText>{t('ERROR', 'Error')}</OText>;
216
204
  }
217
205
 
218
206
  return (
@@ -122,7 +122,7 @@ const CartUI = (props: any) => {
122
122
  >
123
123
  <OText
124
124
  weight="500"
125
- size={21}
125
+ size={18}
126
126
  color={theme.colors.black}
127
127
  >
128
128
  {t('THIS_ORDER_IS_TO', 'This order is to')}
@@ -136,7 +136,7 @@ const CartUI = (props: any) => {
136
136
  bgColor="transparent"
137
137
  borderColor="transparent"
138
138
  style={{ paddingEnd: 0 }}
139
- textStyle={{ color: theme.colors.primary, marginEnd: 0 }}
139
+ textStyle={{ color: theme.colors.primary, marginEnd: 0, fontSize: 18 }}
140
140
  onClick={handleChangeOrderType}
141
141
  />
142
142
  </OrderTypeWrapper>
@@ -187,14 +187,14 @@ const TopBar = (props:any) => {
187
187
  <StyledTopBar>
188
188
  <View>
189
189
  <OText
190
- size={20}
190
+ size={24}
191
191
  weight="700"
192
192
  mBottom={4}
193
193
  >
194
194
  {t('YOUR_ORDER', 'your order')}
195
195
  </OText>
196
196
  <OText
197
- size={20}
197
+ size={18}
198
198
  weight="500"
199
199
  color={theme.colors.mediumGray}
200
200
  >
@@ -55,6 +55,7 @@ const CustomerName = (props: Props): React.ReactElement => {
55
55
  const submitButton = (<OButton
56
56
  text={t('PROCEED_TO_PAY', 'Proceed to Pay')}
57
57
  onClick={handleSubmit(onSubmit)}
58
+ textStyle={{color: theme.colors.primaryContrast, fontSize: 20}}
58
59
  parentStyle={{
59
60
  height: orientationState?.orientation === PORTRAIT
60
61
  ? 50 : 100
@@ -118,14 +119,13 @@ const CustomerName = (props: Props): React.ReactElement => {
118
119
  'Invalid name',
119
120
  ).replace('_attribute_', t('NAME', 'Name')),
120
121
  }
121
-
122
122
  }}
123
123
  defaultValue=""
124
124
  />
125
125
 
126
126
  {orientationState?.orientation === LANDSCAPE && submitButton}
127
127
  </Container>
128
-
128
+
129
129
  {(orientationState?.orientation === PORTRAIT) && (
130
130
  <OSActions>
131
131
  {submitButton}
@@ -18,6 +18,7 @@ import {
18
18
  OSTable,
19
19
  OSActions,
20
20
  OSInputWrapper,
21
+ SentReceipt
21
22
  } from './styles'
22
23
  import { OrderDetailsParams, Product } from '../../types'
23
24
  import { Container } from '../../layouts/Container';
@@ -29,7 +30,7 @@ import { verifyDecimals } from '../../../../../src/utils'
29
30
  import { LANDSCAPE, PORTRAIT, useDeviceOrientation } from '../../../../../src/hooks/DeviceOrientation'
30
31
  import { useTheme } from 'styled-components/native'
31
32
  import { _retrieveStoreData } from '../../../../../src/providers/StoreUtil';
32
-
33
+ import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'
33
34
  const _EMAIL = 'email';
34
35
  const _SMS = 'sms';
35
36
 
@@ -161,7 +162,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
161
162
  setCountReceipts(countReceipts - 1)
162
163
  }
163
164
 
164
- }catch (error) {
165
+ } catch (error : any) {
165
166
  showToast(ToastType.Error, error.message)
166
167
  }
167
168
  setIsLoading(false)
@@ -243,17 +244,19 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
243
244
  marginBottom: 10,
244
245
  }}
245
246
  >
246
-
247
- <OText>{t('SEND_RECEIPT', 'Send receipt')}</OText>
247
+ <SentReceipt>
248
+ <MaterialIcon name='check-circle' color={theme.colors.primary} size={28} />
249
+ <OText size={20} mLeft={10}>{t('SEND_RECEIPT', 'Send receipt')}</OText>
250
+ </SentReceipt>
251
+ <OText size={20}>
252
+ {countReceipts}/5 {t('RECIPTS_REMAINING', 'Recipts remaining')}
253
+ </OText>
248
254
 
249
255
  {/* <OptionSwitch
250
256
  options={optionsToSendReceipt}
251
257
  onChange={setOptionToSendReceipt}
252
258
  /> */}
253
259
  </OSTable>
254
- <OText size={14} style={{alignSelf: 'flex-end'}}>
255
- {countReceipts}/5 {t('RECIPTS_REMAINING', 'Recipts remaining')}
256
- </OText>
257
260
  <OSTable>
258
261
  {optionToSendReceipt?.value === _EMAIL && (
259
262
  <Controller
@@ -334,21 +337,21 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
334
337
  }}
335
338
  >
336
339
  <OSTable>
337
- <OText>
340
+ <View style={{flexDirection: 'row', bottom: 10}}>
338
341
  <OText
339
- size={orientationState?.dimensions?.width * 0.04}
342
+ size={orientationState?.dimensions?.width * 0.039}
340
343
  weight="700"
341
344
  >
342
345
  {t('ORDER_NUMBER', 'Order No.')} {' '}
343
346
  </OText>
344
347
  <OText
345
- size={orientationState?.dimensions?.width * 0.04}
348
+ size={orientationState?.dimensions?.width * 0.039}
346
349
  weight="700"
347
350
  color={theme.colors.primary}
348
351
  >
349
352
  {order?.id}
350
353
  </OText>
351
- </OText>
354
+ </View>
352
355
  </OSTable>
353
356
 
354
357
  {order?.products?.length && (
@@ -392,7 +395,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
392
395
  >
393
396
  {t('PROMO_CODE', 'Promo code')}
394
397
  {'\n'}
395
- <OText weight="400">
398
+ <OText weight="400" style={{fontSize: 14}}>
396
399
  {order?.offer_type === 1 ? `${verifyDecimals(order?.offer_rate, parseNumber)}%` : parsePrice(order?.summary?.discount || order?.discount)} {t('OFF', 'off')}
397
400
  </OText>
398
401
  </OText>
@@ -26,3 +26,7 @@ export const OSInputWrapper = styled.View`
26
26
  min-height: 150px;
27
27
  background-color: #FFF;
28
28
  `
29
+
30
+ export const SentReceipt = styled.View`
31
+ flex-direction: row;
32
+ `
@@ -5,6 +5,7 @@ import styled, { useTheme } from 'styled-components/native'
5
5
  const Wrapper = styled.ScrollView`
6
6
  background-color: ${(props: any) => props.theme.colors.whiteGray};
7
7
  flex-direction: row;
8
+ padding-left: 10px;
8
9
  `
9
10
  const SegItem = styled.View`
10
11
  padding: 24px 12px;
@@ -32,8 +33,7 @@ interface Props {
32
33
  }
33
34
 
34
35
  const OSegment = (props: Props) => {
35
-
36
- var [curIndex, onSelected] = React.useState(props.selectedIdx)
36
+ const [curIndex, onSelected] = React.useState(props.selectedIdx)
37
37
  const onSelectItem = (idx: number) => {
38
38
  onSelected(idx)
39
39
  props.onSelectItem(idx)