ordering-ui-react-native 0.16.93-release → 0.16.94-release

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.
Files changed (21) hide show
  1. package/package.json +1 -1
  2. package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +1 -1
  3. package/themes/business/src/components/Chat/index.tsx +116 -105
  4. package/themes/business/src/components/NewOrderNotification/index.tsx +4 -4
  5. package/themes/original/src/components/AddressForm/index.tsx +9 -1
  6. package/themes/original/src/components/BusinessBasicInformation/index.tsx +4 -2
  7. package/themes/original/src/components/BusinessBasicInformation/styles.tsx +8 -0
  8. package/themes/original/src/components/BusinessController/index.tsx +75 -51
  9. package/themes/original/src/components/BusinessController/styles.tsx +8 -0
  10. package/themes/original/src/components/BusinessFeaturedController/index.tsx +4 -2
  11. package/themes/original/src/components/BusinessFeaturedController/styles.tsx +8 -0
  12. package/themes/original/src/components/BusinessProductsList/index.tsx +4 -2
  13. package/themes/original/src/components/BusinessProductsList/styles.tsx +8 -0
  14. package/themes/original/src/components/BusinessProductsListing/index.tsx +12 -1
  15. package/themes/original/src/components/Messages/index.tsx +2 -1
  16. package/themes/original/src/components/PageBanner/index.tsx +1 -1
  17. package/themes/original/src/components/Promotions/index.tsx +1 -1
  18. package/themes/original/src/components/Promotions/styles.tsx +3 -1
  19. package/themes/original/src/components/SingleProductCard/index.tsx +6 -4
  20. package/themes/original/src/components/SingleProductCard/styles.tsx +9 -1
  21. package/themes/original/src/utils/index.tsx +39 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.16.93-release",
3
+ "version": "0.16.94-release",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -522,7 +522,7 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
522
522
  style={{ borderRadius: 7, height: 45 }}
523
523
  parentStyle={{ width: '100%' }}
524
524
  textStyle={{ color: '#FFF', fontSize: 18 }}
525
- isDisabled={!rejectReason && showTextArea}
525
+ isDisabled={showTextArea && !comments}
526
526
  onClick={() => handleAcceptOrReject()}
527
527
  />
528
528
  </View>
@@ -69,6 +69,8 @@ const ChatUI = (props: MessagesParams) => {
69
69
  const [, { showToast }] = useToast();
70
70
  const theme = useTheme();
71
71
  const [messageList, setMessageList] = useState<any>([])
72
+ const previousStatus = [1, 2, 5, 6, 10, 11, 12, 16, 17]
73
+ const chatDisabled = previousStatus.includes(order?.status)
72
74
 
73
75
  const ORDER_STATUS: any = {
74
76
  0: t('ORDER_STATUS_PENDING', 'Order status pending'),
@@ -176,12 +178,8 @@ const ChatUI = (props: MessagesParams) => {
176
178
  fontSize: 12,
177
179
  },
178
180
  toolbarStyle: {
179
- flexDirection: 'column-reverse',
180
- paddingVertical: 15,
181
- paddingHorizontal: 30,
182
- backgroundColor: theme.colors.white,
183
- borderTopWidth: 1,
184
- borderTopColor: theme.colors.tabBar,
181
+ padding: Platform.OS === 'ios' && isKeyboardShow ? 0 : 10,
182
+ flexDirection: 'column-reverse'
185
183
  },
186
184
  accessoryIcon: {
187
185
  height: 32,
@@ -586,16 +584,12 @@ const ChatUI = (props: MessagesParams) => {
586
584
  };
587
585
 
588
586
  const renderAccessory = () => (
587
+ !chatDisabled &&
589
588
  <View>
590
589
  <Header
591
590
  showsVerticalScrollIndicator={false}
592
591
  showsHorizontalScrollIndicator={false}
593
592
  horizontal
594
- // contentContainerStyle={{
595
- // justifyContent:
596
- // orientation === 'Landscape' ? 'center' : 'space-between',
597
- // width: '100%',
598
- // }}
599
593
  nestedScrollEnabled={true}
600
594
  >
601
595
  {user?.level !== 2 && (
@@ -766,113 +760,130 @@ const ChatUI = (props: MessagesParams) => {
766
760
  containerStyle={styles.toolbarStyle}
767
761
  primaryStyle={{ alignItems: 'center', justifyContent: 'space-between' }}
768
762
  accessoryStyle={{ position: 'relative', marginBottom: 45 }}
769
- renderAccessory={order ? () => renderAccessory && renderAccessory() : undefined}
763
+ renderAccessory={() => renderAccessory()}
770
764
  />
771
765
  );
772
766
 
773
767
  const renderComposer = (props: any) => (
774
- <View
775
- style={{
776
- flexDirection: 'row',
777
- height: 44,
778
- width: '85%',
779
- backgroundColor: theme.colors.composerView,
780
- borderRadius: 7.6,
781
- alignItems: 'center',
782
- justifyContent: 'center',
783
- paddingRight: 10,
784
- }}>
785
- <Composer
786
- {...props}
787
- textInputStyle={{
788
- borderRadius: 7.6,
789
- borderColor: theme.colors.transparent,
790
- borderWidth: 0,
791
- color: '#010300',
792
- }}
793
- textInputProps={{
794
- value: message,
795
- onSubmitEditing: onSubmit,
796
- returnKeyType: message ? 'send' : 'done',
797
- blurOnSubmit: true,
798
- multiline: false,
799
- numberOfLines: 1,
800
- autoCorrect: false,
801
- autoCompleteType: 'off',
802
- enablesReturnKeyAutomatically: false,
803
- selectionColor: theme.colors.primary,
768
+ chatDisabled ? (
769
+ <View
770
+ style={{
771
+ width: '100%',
772
+ flexDirection: 'column',
773
+ alignItems: 'center'
804
774
  }}
805
- placeholder={t('WRITE_MESSAGE', 'Write message')}
806
- placeholderTextColor={theme.colors.composerPlaceHolder}
807
- />
808
-
809
- <TouchableOpacity
810
- onPress={() => {
811
- setImage && setImage(null);
812
- setIsShowSignaturePad(!isShowSignaturePad);
813
- }}>
775
+ >
814
776
  <MaterialCommunityIcon
815
- name="pen"
816
- color={
817
- isShowSignaturePad ? theme.colors.primary : theme.colors.arrowColor
818
- }
777
+ name='close-octagon-outline'
819
778
  size={24}
820
779
  />
821
- </TouchableOpacity>
822
-
823
- {!file.type && (
824
- <Actions
780
+ <OText size={14}>{t('NOT_SEND_MESSAGES', 'You can\'t send messages because the order has ended')}</OText>
781
+ </View>
782
+ ) : (
783
+ <View
784
+ style={{
785
+ flexDirection: 'row',
786
+ height: 44,
787
+ width: '85%',
788
+ backgroundColor: theme.colors.composerView,
789
+ borderRadius: 7.6,
790
+ alignItems: 'center',
791
+ justifyContent: 'center',
792
+ paddingRight: 10,
793
+ }}>
794
+ <Composer
825
795
  {...props}
826
- containerStyle={styles.containerActions}
827
- optionTintColor="#222845"
828
- icon={() => (
829
- <>
830
- {!file?.type && (
831
- <>
832
- <OIconButton
833
- borderColor={theme.colors.transparent}
834
- icon={
835
- !isShowSignaturePad && image
836
- ? { uri: image }
837
- : theme.images.general.imageChat
838
- }
839
- iconStyle={{
840
- borderRadius: image ? 10 : 0,
841
- width: image ? 32 : 28,
842
- height: image ? 32 : 28,
843
- }}
844
- onClick={handleImagePicker}
845
- iconCover
846
- />
847
-
848
- {image && !isShowSignaturePad && (
849
- <TouchableOpacity
850
- style={{
851
- position: 'absolute',
852
- top: -5,
853
- right: -5,
854
- borderColor: theme.colors.backgroundDark,
855
- backgroundColor: theme.colors.white,
856
- borderRadius: 25,
857
- }}
858
- onPress={() => removeImage()}>
859
- <MaterialCommunityIcon
860
- name="close-circle-outline"
861
- color={theme.colors.backgroundDark}
862
- size={24}
863
- />
864
- </TouchableOpacity>
865
- )}
866
- </>
867
- )}
868
- </>
869
- )}
796
+ textInputStyle={{
797
+ borderRadius: 7.6,
798
+ borderColor: theme.colors.transparent,
799
+ borderWidth: 0,
800
+ color: '#010300',
801
+ }}
802
+ textInputProps={{
803
+ value: message,
804
+ onSubmitEditing: onSubmit,
805
+ returnKeyType: message ? 'send' : 'done',
806
+ blurOnSubmit: true,
807
+ multiline: false,
808
+ numberOfLines: 1,
809
+ autoCorrect: false,
810
+ autoCompleteType: 'off',
811
+ enablesReturnKeyAutomatically: false,
812
+ selectionColor: theme.colors.primary,
813
+ }}
814
+ placeholder={t('WRITE_MESSAGE', 'Write message')}
815
+ placeholderTextColor={theme.colors.composerPlaceHolder}
870
816
  />
871
- )}
872
- </View>
817
+
818
+ <TouchableOpacity
819
+ onPress={() => {
820
+ setImage && setImage(null);
821
+ setIsShowSignaturePad(!isShowSignaturePad);
822
+ }}>
823
+ <MaterialCommunityIcon
824
+ name="pen"
825
+ color={
826
+ isShowSignaturePad ? theme.colors.primary : theme.colors.arrowColor
827
+ }
828
+ size={24}
829
+ />
830
+ </TouchableOpacity>
831
+
832
+ {!file.type && (
833
+ <Actions
834
+ {...props}
835
+ containerStyle={styles.containerActions}
836
+ optionTintColor="#222845"
837
+ icon={() => (
838
+ <>
839
+ {!file?.type && (
840
+ <>
841
+ <OIconButton
842
+ borderColor={theme.colors.transparent}
843
+ icon={
844
+ !isShowSignaturePad && image
845
+ ? { uri: image }
846
+ : theme.images.general.imageChat
847
+ }
848
+ iconStyle={{
849
+ borderRadius: image ? 10 : 0,
850
+ width: image ? 32 : 28,
851
+ height: image ? 32 : 28,
852
+ }}
853
+ onClick={handleImagePicker}
854
+ iconCover
855
+ />
856
+
857
+ {image && !isShowSignaturePad && (
858
+ <TouchableOpacity
859
+ style={{
860
+ position: 'absolute',
861
+ top: -5,
862
+ right: -5,
863
+ borderColor: theme.colors.backgroundDark,
864
+ backgroundColor: theme.colors.white,
865
+ borderRadius: 25,
866
+ }}
867
+ onPress={() => removeImage()}>
868
+ <MaterialCommunityIcon
869
+ name="close-circle-outline"
870
+ color={theme.colors.backgroundDark}
871
+ size={24}
872
+ />
873
+ </TouchableOpacity>
874
+ )}
875
+ </>
876
+ )}
877
+ </>
878
+ )}
879
+ />
880
+ )}
881
+ </View>
882
+ )
873
883
  );
874
884
 
875
885
  const renderSend = (props: any) => (
886
+ !chatDisabled &&
876
887
  <Send
877
888
  {...props}
878
889
  disabled={
@@ -44,7 +44,7 @@ const NewOrderNotificationUI = (props: any) => {
44
44
  },
45
45
  }
46
46
 
47
- const notificationSound = new Sound(theme.sounds.notification);
47
+ const notificationSound = new Sound(theme.sounds.notification, '', () => { });
48
48
 
49
49
  let _timeout: any = null
50
50
 
@@ -74,11 +74,11 @@ const NewOrderNotificationUI = (props: any) => {
74
74
  await fetch(`${ordering.root}/users/${user.id}/locations`, {
75
75
  method: 'POST',
76
76
  body: JSON.stringify({
77
- location: JSON.stringify({location: `{lat: ${location.latitude}, lng: ${location.longitude}}`})
77
+ location: JSON.stringify({ location: `{lat: ${location.latitude}, lng: ${location.longitude}}` })
78
78
  }),
79
79
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }
80
80
  })
81
- } catch {}
81
+ } catch { }
82
82
  const duration = moment.duration(moment().diff(moment.utc(value?.last_driver_assigned_at)))
83
83
  const assignedSecondsDiff = duration.asSeconds()
84
84
  if (assignedSecondsDiff < 5 && !isBusinessApp) {
@@ -88,7 +88,7 @@ const NewOrderNotificationUI = (props: any) => {
88
88
  if (evtType === 3 || value.author_id === user.id) return
89
89
  handlePlayNotificationSound({
90
90
  evt: evtType,
91
- orderId: evtList[evtType].event === 'messages' ? value?.order_id : value?.id
91
+ orderId: value?.order_id
92
92
  })
93
93
  }
94
94
 
@@ -16,6 +16,8 @@ import {
16
16
  useToast,
17
17
  ToastType
18
18
  } from 'ordering-components/native';
19
+ import { DeviceOrientationMethods } from '../../../../../src/hooks/DeviceOrientation'
20
+
19
21
  import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
20
22
  import Spinner from 'react-native-loading-spinner-overlay';
21
23
  import { useForm, Controller } from 'react-hook-form';
@@ -38,6 +40,8 @@ import {
38
40
  import { GPSButton } from '../GPSButton';
39
41
  import { ScrollView } from 'react-native-gesture-handler';
40
42
 
43
+ const { useDeviceOrientation } = DeviceOrientationMethods
44
+
41
45
  const inputNames = [
42
46
  { name: 'address', code: 'Address' },
43
47
  { name: 'internal_number', code: 'Internal number' },
@@ -66,6 +70,8 @@ const AddressFormUI = (props: AddressFormParams) => {
66
70
  } = props;
67
71
 
68
72
  const theme = useTheme();
73
+ const [orientationState] = useDeviceOrientation();
74
+
69
75
  const [autoCompleteInputFocused, setAutoCompleteInputFocused] = useState(false)
70
76
 
71
77
  const tagsName = [
@@ -75,6 +81,8 @@ const AddressFormUI = (props: AddressFormParams) => {
75
81
  { icon: theme.images.general.tag_plus, value: 'other' },
76
82
  ];
77
83
 
84
+ const HEIGHT_SCREEN = orientationState?.dimensions?.height
85
+
78
86
  const styles = StyleSheet.create({
79
87
  iconContainer: {
80
88
  display: 'flex',
@@ -524,7 +532,7 @@ const AddressFormUI = (props: AddressFormParams) => {
524
532
  />
525
533
  </View>
526
534
  <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
527
- <AddressFormContainer style={{ height: 600, overflow: 'scroll' }}>
535
+ <AddressFormContainer style={{ height: HEIGHT_SCREEN * .78, overflow: 'scroll' }}>
528
536
  <View>
529
537
  <FormInput>
530
538
  <AutocompleteInput>
@@ -5,7 +5,7 @@ import { useUtils, useOrder, useLanguage } from 'ordering-components/native';
5
5
  import { useTheme } from 'styled-components/native';
6
6
  import { OIcon, OText, OModal } from '../shared';
7
7
  import { BusinessBasicInformationParams } from '../../types';
8
- import { convertHoursToMinutes, shape } from '../../utils';
8
+ import { convertHoursToMinutes, lightenDarkenColor, shape } from '../../utils';
9
9
  import MaterialComIcon from 'react-native-vector-icons/MaterialCommunityIcons'
10
10
  import dayjs from 'dayjs';
11
11
  import timezone from 'dayjs/plugin/timezone';
@@ -351,13 +351,15 @@ export const BusinessBasicInformation = (
351
351
  {business?.ribbon?.enabled && (
352
352
  <RibbonBox
353
353
  bgColor={business?.ribbon?.color}
354
+ colorText={lightenDarkenColor(business?.ribbon?.color)}
355
+ borderRibbon={lightenDarkenColor(business?.ribbon?.color)}
354
356
  isRoundRect={business?.ribbon?.shape === shape?.rectangleRound}
355
357
  isCapsule={business?.ribbon?.shape === shape?.capsuleShape}
356
358
  >
357
359
  <OText
358
360
  size={10}
359
361
  weight={'400'}
360
- color={theme.colors.white}
362
+ color={lightenDarkenColor(business?.ribbon?.color) ? theme.colors.black : theme.colors.white}
361
363
  numberOfLines={2}
362
364
  ellipsizeMode='tail'
363
365
  lineHeight={13}
@@ -64,6 +64,14 @@ export const RibbonBox = styled.View`
64
64
  ${(props: any) => props.isCapsule && css`
65
65
  border-radius: 50px;
66
66
  `}
67
+
68
+ ${(props: any) => props.colorText && css`
69
+ color: ${props.colorText ? 'black' : 'white'};
70
+ `}
71
+
72
+ ${(props: any) => props.borderRibbon && css`
73
+ border: 1px solid ${props.borderRibbon ? 'black' : 'white'};
74
+ `}
67
75
  `
68
76
 
69
77
  export const SocialListWrapper = styled.ScrollView`
@@ -14,7 +14,7 @@ import { OIcon, OText } from '../shared';
14
14
  import { Dimensions, StyleSheet, Vibration, View } from 'react-native';
15
15
  import { InView } from 'react-native-intersection-observer'
16
16
  import { BusinessControllerParams } from '../../types';
17
- import { convertHoursToMinutes, shape } from '../../utils';
17
+ import { convertHoursToMinutes, lightenDarkenColor, shape } from '../../utils';
18
18
 
19
19
  import {
20
20
  BusinessHero,
@@ -65,6 +65,16 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
65
65
  const windowHeight = Dimensions.get('window').height
66
66
  const [isIntersectionObserver, setIsIntersectionObserver] = useState(!enableIntersection)
67
67
 
68
+ const hideBusinessLogo = theme?.business_listing_view?.components?.business?.components?.logo?.hidden
69
+ const hideBusinessFee = theme?.business_listing_view?.components?.business?.components?.fee?.hidden
70
+ const hideBusinessTime = theme?.business_listing_view?.components?.business?.components?.time?.hidden
71
+ const hideBusinessDistance = theme?.business_listing_view?.components?.business?.components?.distance?.hidden
72
+ const hideBusinessReviews = theme?.business_listing_view?.components?.business?.components?.reviews?.hidden
73
+ const hideBusinessFavorite = theme?.business_listing_view?.components?.business?.components?.favorite?.hidden
74
+ const hideBusinessOffer = theme?.business_listing_view?.components?.business?.components?.offer?.hidden
75
+ const hideBusinessHeader = theme?.business_listing_view?.components?.business?.components?.header?.hidden
76
+ const hideBusinessFavoriteBadge = theme?.business_listing_view?.components?.business?.components?.featured_badge?.hidden
77
+
68
78
  const textSize = isCustomLayout ? 12 : 10
69
79
  const cardHeight = windowHeight * 0.3
70
80
 
@@ -175,13 +185,15 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
175
185
  {business?.ribbon?.enabled && (
176
186
  <RibbonBox
177
187
  bgColor={business?.ribbon?.color}
188
+ colorText={lightenDarkenColor(business?.ribbon?.color)}
189
+ borderRibbon={lightenDarkenColor(business?.ribbon?.color)}
178
190
  isRoundRect={business?.ribbon?.shape === shape?.rectangleRound}
179
191
  isCapsule={business?.ribbon?.shape === shape?.capsuleShape}
180
192
  >
181
193
  <OText
182
194
  size={10}
183
195
  weight={'400'}
184
- color={theme.colors.white}
196
+ color={lightenDarkenColor(business?.ribbon?.color) ? theme.colors.black : theme.colors.white}
185
197
  numberOfLines={2}
186
198
  ellipsizeMode='tail'
187
199
  lineHeight={13}
@@ -191,20 +203,22 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
191
203
  </RibbonBox>
192
204
  )}
193
205
  <BusinessHero>
194
- <FastImage
195
- style={{ height: isCustomLayout ? cardHeight * 0.66 : 120 }}
196
- source={(businessHeader || business?.header) ? {
197
- uri: optimizeImage(businessHeader || business?.header, 'h_500,c_limit'),
198
- priority: FastImage.priority.normal,
199
- } : theme.images.dummies.businessHeader}
200
- resizeMode={FastImage.resizeMode.cover}
201
- />
202
- {(businessFeatured ?? business?.featured) && (
206
+ {!hideBusinessHeader && (
207
+ <FastImage
208
+ style={{ height: isCustomLayout ? cardHeight * 0.66 : 120 }}
209
+ source={(businessHeader || business?.header || typeof theme.images.dummies.businessHeader === 'string') ? {
210
+ uri: optimizeImage(businessHeader || business?.header || theme.images.dummies.businessHeader, 'h_500,c_limit'),
211
+ priority: FastImage.priority.normal,
212
+ } : theme.images.dummies.businessHeader}
213
+ resizeMode={FastImage.resizeMode.cover}
214
+ />
215
+ )}
216
+ {(businessFeatured ?? business?.featured) && !hideBusinessFavoriteBadge && (
203
217
  <View style={styles.featured}>
204
218
  <FontAwesomeIcon name="crown" size={26} color="gold" />
205
219
  </View>
206
220
  )}
207
- {(!isCustomLayout) && (
221
+ {(!isCustomLayout) && !hideBusinessOffer && (
208
222
  getBusinessOffer((business?.offers)) &&
209
223
  <OfferBox>
210
224
  <OText
@@ -231,19 +245,21 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
231
245
  </BusinessHero>
232
246
  <BusinessContent>
233
247
  <BusinessInfo style={isCustomLayout && { position: 'absolute', bottom: 85, left: 15 }}>
234
- <BusinessLogo style={styles.businessLogo}>
235
- <FastImage
236
- style={{ width: 56, height: 56 }}
237
- source={(businessLogo || business?.logo) ? {
238
- uri: optimizeImage(businessLogo || business?.logo, 'h_150,c_limit'),
239
- priority: FastImage.priority.normal,
240
- } : theme.images.dummies.businessLogo}
241
- resizeMode={FastImage.resizeMode.cover}
242
- />
243
- </BusinessLogo>
244
- {!isCustomLayout && (
248
+ {!hideBusinessLogo && (
249
+ <BusinessLogo style={styles.businessLogo}>
250
+ <FastImage
251
+ style={{ width: 56, height: 56 }}
252
+ source={(businessLogo || business?.logo || typeof theme.images.dummies.businessLogo === 'string') ? {
253
+ uri: optimizeImage(businessLogo || business?.logo || theme.images.dummies.businessLogo, 'h_150,c_limit'),
254
+ priority: FastImage.priority.normal,
255
+ } : theme.images.dummies.businessLogo}
256
+ resizeMode={FastImage.resizeMode.cover}
257
+ />
258
+ </BusinessLogo>
259
+ )}
260
+ {!isCustomLayout && (!hideBusinessFavorite || !hideBusinessReviews) && (
245
261
  <ReviewAndFavorite>
246
- {(businessReviews?.reviews?.total > 0 ?? business?.reviews?.total > 0) && (
262
+ {(businessReviews?.reviews?.total > 0 ?? business?.reviews?.total > 0) && !hideBusinessReviews && (
247
263
  <Reviews>
248
264
  <OIcon src={theme.images.general.star} width={12} style={styles.starIcon} />
249
265
  <OText size={10} style={{ lineHeight: 15 }}>
@@ -251,15 +267,17 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
251
267
  </OText>
252
268
  </Reviews>
253
269
  )}
254
- <LottieAnimation
255
- type='favorite'
256
- onClick={handleChangeFavorite}
257
- initialValue={business?.favorite ? 0.75 : 0}
258
- toValue={business?.favorite ? 0 : 0.75}
259
- disableAnimation={!auth}
260
- iconProps={{ color: theme.colors.danger5, size: 18 }}
261
- isActive={business?.favorite}
262
- />
270
+ {!hideBusinessFavorite && (
271
+ <LottieAnimation
272
+ type='favorite'
273
+ onClick={handleChangeFavorite}
274
+ initialValue={business?.favorite ? 0.5 : 0}
275
+ toValue={business?.favorite ? 0 : 0.5}
276
+ disableAnimation={!auth}
277
+ iconProps={{ color: theme.colors.danger5, size: 18 }}
278
+ isActive={business?.favorite}
279
+ />
280
+ )}
263
281
  </ReviewAndFavorite>
264
282
  )}
265
283
  </BusinessInfo>
@@ -270,9 +288,9 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
270
288
  weight={'500'}>
271
289
  {business?.name}
272
290
  </OText>
273
- {isCustomLayout && (
291
+ {isCustomLayout && (!hideBusinessFavorite || !hideBusinessReviews) && (
274
292
  <ReviewAndFavorite>
275
- {(businessReviews?.reviews?.total > 0 ?? business?.reviews?.total > 0) && (
293
+ {(businessReviews?.reviews?.total > 0 ?? business?.reviews?.total > 0) && !hideBusinessReviews && (
276
294
  <Reviews>
277
295
  <OIcon src={theme.images.general.star} width={12} style={styles.starIcon} />
278
296
  <OText size={10} style={{ lineHeight: 15 }}>
@@ -280,15 +298,17 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
280
298
  </OText>
281
299
  </Reviews>
282
300
  )}
283
- <LottieAnimation
284
- type='favorite'
285
- onClick={handleChangeFavorite}
286
- initialValue={business?.favorite ? 0.75 : 0}
287
- toValue={business?.favorite ? 0 : 0.75}
288
- disableAnimation={!auth}
289
- iconProps={{ color: theme.colors.danger5, size: 18 }}
290
- isActive={business?.favorite}
291
- />
301
+ {!hideBusinessFavorite && (
302
+ <LottieAnimation
303
+ type='favorite'
304
+ onClick={handleChangeFavorite}
305
+ initialValue={business?.favorite ? 0.5 : 0}
306
+ toValue={business?.favorite ? 0 : 0.5}
307
+ disableAnimation={!auth}
308
+ iconProps={{ color: theme.colors.danger5, size: 18 }}
309
+ isActive={business?.favorite}
310
+ />
311
+ )}
292
312
  </ReviewAndFavorite>
293
313
  )}
294
314
  </View>
@@ -304,17 +324,21 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
304
324
  </View>
305
325
  ) : (
306
326
  <View style={styles.bullet}>
307
- {orderState?.options?.type === 1 && (
327
+ {orderState?.options?.type === 1 && !hideBusinessFee && (
308
328
  <OText size={textSize} color={theme.colors.textSecondary}>
309
329
  {`${t('DELIVERY_FEE', 'Delivery fee')} ${parsePrice(businessDeliveryPrice ?? business?.delivery_price) + ' \u2022 '}`}
310
330
  </OText>
311
331
  )}
312
- <OText size={textSize} color={theme.colors.textSecondary}>{`${convertHoursToMinutes(
313
- orderState?.options?.type === 1
314
- ? (businessDeliveryTime ?? business?.delivery_time)
315
- : (businessPickupTime ?? business?.pickup_time),
316
- )} \u2022 `}</OText>
317
- <OText size={textSize} color={theme.colors.textSecondary}>{parseDistance(businessDistance ?? business?.distance)}</OText>
332
+ {!hideBusinessTime && (
333
+ <OText size={textSize} color={theme.colors.textSecondary}>{`${convertHoursToMinutes(
334
+ orderState?.options?.type === 1
335
+ ? (businessDeliveryTime ?? business?.delivery_time)
336
+ : (businessPickupTime ?? business?.pickup_time),
337
+ )} \u2022 `}</OText>
338
+ )}
339
+ {!hideBusinessDistance && (
340
+ <OText size={textSize} color={theme.colors.textSecondary}>{parseDistance(businessDistance ?? business?.distance)}</OText>
341
+ )}
318
342
  </View>
319
343
  )}
320
344
  </Metadata>
@@ -72,6 +72,14 @@ export const RibbonBox = styled.View`
72
72
  ${(props: any) => props.isCapsule && css`
73
73
  border-radius: 50px;
74
74
  `}
75
+
76
+ ${(props: any) => props.colorText && css`
77
+ color: ${props.colorText ? 'black' : 'white'};
78
+ `}
79
+
80
+ ${(props: any) => props.borderRibbon && css`
81
+ border: 1px solid ${props.borderRibbon ? 'black' : 'white'};
82
+ `}
75
83
  `
76
84
 
77
85
  export const OfferBox = styled.View`
@@ -9,7 +9,7 @@ import { useTheme } from 'styled-components/native';
9
9
  import { OIcon, OText } from '../shared';
10
10
  import { StyleSheet, useWindowDimensions, View } from 'react-native';
11
11
  import { BusinessControllerParams } from '../../types';
12
- import { convertHoursToMinutes, shape } from '../../utils';
12
+ import { convertHoursToMinutes, lightenDarkenColor, shape } from '../../utils';
13
13
  import {
14
14
  Card,
15
15
  BusinessHero,
@@ -101,13 +101,15 @@ export const BusinessFeaturedCtrlUI = (props: BusinessControllerParams) => {
101
101
  {business?.ribbon?.enabled && (
102
102
  <RibbonBox
103
103
  bgColor={business?.ribbon?.color}
104
+ colorText={lightenDarkenColor(business?.ribbon?.color)}
105
+ borderRibbon={lightenDarkenColor(business?.ribbon?.color)}
104
106
  isRoundRect={business?.ribbon?.shape === shape?.rectangleRound}
105
107
  isCapsule={business?.ribbon?.shape === shape?.capsuleShape}
106
108
  >
107
109
  <OText
108
110
  size={10}
109
111
  weight={'400'}
110
- color={theme.colors.white}
112
+ color={lightenDarkenColor(business?.ribbon?.color) ? theme.colors.black : theme.colors.white}
111
113
  numberOfLines={2}
112
114
  ellipsizeMode='tail'
113
115
  lineHeight={13}
@@ -70,4 +70,12 @@ export const RibbonBox = styled.View`
70
70
  ${(props: any) => props.isCapsule && css`
71
71
  border-radius: 50px;
72
72
  `}
73
+
74
+ ${(props: any) => props.colorText && css`
75
+ color: ${props.colorText ? 'black' : 'white'};
76
+ `}
77
+
78
+ ${(props: any) => props.borderRibbon && css`
79
+ border: 1px solid ${props.borderRibbon ? 'black' : 'white'};
80
+ `}
73
81
  `
@@ -9,7 +9,7 @@ import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
9
9
  import { View, ScrollView } from 'react-native';
10
10
  import { StyleSheet } from 'react-native';
11
11
  import { useTheme } from 'styled-components/native';
12
- import { shape } from '../../utils'
12
+ import { lightenDarkenColor, shape } from '../../utils'
13
13
  import { CategoryDescriptionMemoized } from './CategoryDescription';
14
14
  import { OrderItAgain } from '../OrderItAgain'
15
15
  import { SubcategoriesComponentMemoized } from './SubcategoriesComponent';
@@ -186,13 +186,15 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
186
186
  {category?.ribbon?.enabled && (
187
187
  <RibbonBox
188
188
  bgColor={category?.ribbon?.color}
189
+ colorText={lightenDarkenColor(category?.ribbon?.color)}
190
+ borderRibbon={lightenDarkenColor(category?.ribbon?.color)}
189
191
  isRoundRect={category?.ribbon?.shape === shape?.rectangleRound}
190
192
  isCapsule={category?.ribbon?.shape === shape?.capsuleShape}
191
193
  >
192
194
  <OText
193
195
  size={10}
194
196
  weight={'400'}
195
- color={theme.colors.white}
197
+ color={lightenDarkenColor(category?.ribbon?.color) ? theme.colors.black : theme.colors.white}
196
198
  numberOfLines={2}
197
199
  ellipsizeMode='tail'
198
200
  lineHeight={13}
@@ -27,6 +27,14 @@ export const RibbonBox = styled.View`
27
27
  ${(props: any) => props.isCapsule && css`
28
28
  border-radius: 50px;
29
29
  `}
30
+
31
+ ${(props: any) => props.colorText && css`
32
+ color: ${props.colorText ? 'black' : 'white'};
33
+ `}
34
+
35
+ ${(props: any) => props.borderRibbon && css`
36
+ border: 1px solid ${props.borderRibbon ? 'black' : 'white'};
37
+ `}
30
38
  `
31
39
 
32
40
  export const SubCategoriesContainer = styled.View`
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react'
2
- import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Vibration } from 'react-native'
2
+ import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Vibration, BackHandler } from 'react-native'
3
3
  import { IOScrollView } from 'react-native-intersection-observer'
4
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
5
  import { useTheme } from 'styled-components/native';
@@ -343,6 +343,17 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
343
343
  }
344
344
  }, [business?.lazy_load_products_recommended, selectedCategoryId, categorySelected?.id, viewedCategory])
345
345
 
346
+ useEffect(() => {
347
+ const handleArrowBack: any = () => {
348
+ navigation.goBack()
349
+ return true
350
+ }
351
+ BackHandler.addEventListener('hardwareBackPress', handleArrowBack);
352
+ return () => {
353
+ BackHandler.removeEventListener('hardwareBackPress', handleArrowBack);
354
+ }
355
+ }, [])
356
+
346
357
  return (
347
358
  <>
348
359
  <View style={{ flex: 1, backgroundColor: backgroundColor }}>
@@ -171,7 +171,7 @@ const MessagesUI = (props: MessagesParams) => {
171
171
  image: message.source,
172
172
  system: message.type === 1,
173
173
  user: {
174
- _id: message.author && message.author.id ,
174
+ _id: message.author && message.author.id,
175
175
  name: message.author && message.author.name,
176
176
  avatar: message.author && (message.author.id !== user.id && type === USER_TYPE.DRIVER ? order?.driver?.photo : order?.business?.logo)
177
177
  }
@@ -242,6 +242,7 @@ const MessagesUI = (props: MessagesParams) => {
242
242
 
243
243
  const renderAccessory = () => {
244
244
  return (
245
+ !chatDisabled &&
245
246
  <QuickMessageContainer
246
247
  style={{
247
248
  marginLeft: 10,
@@ -44,7 +44,7 @@ const PageBannerUI = (props: any) => {
44
44
  })
45
45
 
46
46
  const onRedirect = (route: string, params?: any) => {
47
- navigation.navigate(route, params)
47
+ navigation.push(route, params)
48
48
  }
49
49
 
50
50
  const handleGoToPage = (item: any) => {
@@ -143,7 +143,7 @@ const PromotionsUI = (props: PromotionParams) => {
143
143
  <WrapperSingleOffer key={offer.id}>
144
144
  <SingleOfferContainer>
145
145
  <FastImage
146
- style={{ height: 80, width: 80, aspectRatio: 3 / 2, borderRadius: 8 }}
146
+ style={{ height: 80, width: 80, aspectRatio: 1, borderRadius: 8 }}
147
147
  source={typeof offer?.image !== 'number' ? {
148
148
  uri: optimizeImage(offer?.image, 'h_1024,c_limit'),
149
149
  priority: FastImage.priority.normal,
@@ -9,6 +9,7 @@ export const PromotionsContainer = styled.View`
9
9
  export const WrapperSingleOffer = styled.View`
10
10
  flex-direction: column;
11
11
  width: 100%;
12
+ margin-bottom: 30px;
12
13
  `
13
14
 
14
15
  export const SingleOfferContainer = styled.View`
@@ -16,11 +17,12 @@ export const SingleOfferContainer = styled.View`
16
17
  width: 100%;
17
18
  justify-content: space-between;
18
19
  align-items: center;
19
- margin-bottom: 20px;
20
+ margin-bottom: 10px;
20
21
  `
21
22
 
22
23
  export const OfferInformation = styled.View`
23
24
  justify-content: space-between;
25
+ min-width: 70%;
24
26
  max-width: 70%;
25
27
  `
26
28
 
@@ -17,7 +17,7 @@ import { InView } from 'react-native-intersection-observer'
17
17
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
18
18
  import { OButton, OIcon, OText } from '../shared';
19
19
  import FastImage from 'react-native-fast-image'
20
- import { shape } from '../../utils';
20
+ import { lightenDarkenColor, shape } from '../../utils';
21
21
  import { LottieAnimation } from '../LottieAnimation';
22
22
  import { CardAnimation } from '../shared/CardAnimation'
23
23
 
@@ -109,7 +109,7 @@ const SingleProductCardUI = React.memo((props: SingleProductCardParams) => {
109
109
  },
110
110
  productTagsStyle: {
111
111
  width: 30,
112
- height: 30,
112
+ height: 30,
113
113
  marginRight: 5
114
114
  }
115
115
  });
@@ -222,7 +222,7 @@ const SingleProductCardUI = React.memo((props: SingleProductCardParams) => {
222
222
  showsHorizontalScrollIndicator={false}
223
223
  horizontal
224
224
  style={{ marginLeft: 10 }}
225
- contentContainerStyle={{flexGrow: 1}}
225
+ contentContainerStyle={{ flexGrow: 1 }}
226
226
  >
227
227
  {product?.tags.map((tag: any, i: any) => (
228
228
  <TouchableWithoutFeedback key={i}>
@@ -266,13 +266,15 @@ const SingleProductCardUI = React.memo((props: SingleProductCardParams) => {
266
266
  {!!product?.ribbon?.enabled && (
267
267
  <RibbonBox
268
268
  bgColor={product?.ribbon?.color}
269
+ colorText={lightenDarkenColor(product?.ribbon?.color)}
270
+ borderRibbon={lightenDarkenColor(product?.ribbon?.color)}
269
271
  isRoundRect={product?.ribbon?.shape === shape?.rectangleRound}
270
272
  isCapsule={product?.ribbon?.shape === shape?.capsuleShape}
271
273
  >
272
274
  <OText
273
275
  size={textSize}
274
276
  weight={'400'}
275
- color={theme.colors.white}
277
+ color={lightenDarkenColor(product?.ribbon?.color) ? theme.colors.black : theme.colors.white}
276
278
  numberOfLines={2}
277
279
  ellipsizeMode='tail'
278
280
  lineHeight={13}
@@ -18,7 +18,7 @@ export const QuantityContainer = styled.View`
18
18
  background: ${({ theme }: any) => theme.colors.primary};
19
19
  align-items: center;
20
20
  justify-content: center;
21
- ${({businessSingleId} : any) => businessSingleId ? css`
21
+ ${({ businessSingleId }: any) => businessSingleId ? css`
22
22
  left: 0;
23
23
  ` : css`
24
24
  right: 0;
@@ -63,4 +63,12 @@ export const RibbonBox = styled.View`
63
63
  ${(props: any) => props.isCapsule && css`
64
64
  border-radius: 50px;
65
65
  `}
66
+
67
+ ${(props: any) => props.colorText && css`
68
+ color: ${props.colorText ? 'black' : 'white'};
69
+ `}
70
+
71
+ ${(props: any) => props.borderRibbon && css`
72
+ border: 1px solid ${props.borderRibbon ? 'black' : 'white'};
73
+ `}
66
74
  `
@@ -564,8 +564,46 @@ export const getOrderStatus = (s: string) => {
564
564
  image: theme.images.order.status8
565
565
  }
566
566
  ];
567
-
567
+
568
568
  const objectStatus = orderStatus.find((o) => o.key === status);
569
569
 
570
570
  return objectStatus && objectStatus;
571
571
  }
572
+
573
+ /**
574
+ * Function to get brightness of color.
575
+ */
576
+ export const lightenDarkenColor = (color: any) => {
577
+
578
+ let r, g, b, hsp
579
+ if (!color) return
580
+ if (color.match(/^rgb/)) {
581
+ // If HEX --> store the red, green, blue values in separate variables
582
+ color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/)
583
+
584
+ r = color[1]
585
+ g = color[2]
586
+ b = color[3]
587
+ } else {
588
+ // If RGB --> Convert it to HEX
589
+ color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))
590
+
591
+ r = color >> 16
592
+ g = color >> 8 & 255
593
+ b = color & 255
594
+ }
595
+
596
+ // HSP (Highly Sensitive Poo) equation
597
+ hsp = Math.sqrt(
598
+ 0.299 * (r * r) +
599
+ 0.587 * (g * g) +
600
+ 0.114 * (b * b)
601
+ )
602
+
603
+ // Using the HSP value, determine whether the color is light or dark
604
+ if (hsp > 197) {
605
+ return true //is light color
606
+ } else {
607
+ return false
608
+ }
609
+ }