ordering-ui-react-native 0.15.41 → 0.15.44

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.15.41",
3
+ "version": "0.15.44",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -31,6 +31,7 @@ const BusinessProductsList = (props: any) => {
31
31
  'open',
32
32
  'about',
33
33
  'description',
34
+ 'ribbon',
34
35
  'address',
35
36
  'location',
36
37
  'schedule',
@@ -77,6 +77,7 @@ const OrdersListManagerUI = (props: OrdersOptionParams) => {
77
77
  const [openSearchModal, setOpenSearchModal] = useState(false)
78
78
  const [openSLASettingModal, setOpenSLASettingModal] = useState(false)
79
79
  const [slaSettingTime, setSlaSettingTime] = useState(6000)
80
+ const [configState] = useConfig()
80
81
  const [currentDeliveryType, setCurrentDeliveryType] = useState('Delivery')
81
82
  const [search, setSearch] = useState(defaultSearchList)
82
83
  const [selectedTabStatus, setSelectedTabStatus] = useState<any>([])
@@ -311,55 +312,57 @@ const OrdersListManagerUI = (props: OrdersOptionParams) => {
311
312
  />
312
313
  </IconWrapper>
313
314
  </View>
314
- <View style={styles.SLAwrapper}>
315
- <View style={{ flex: 0.5 }}>
316
- <OButton
317
- text={t('SLA_SETTING', 'SLA’s Settings')}
318
- textStyle={{ color: theme.colors.backArrow }}
319
- imgRightSrc={null}
320
- style={{
321
- backgroundColor: theme.colors.inputChat,
322
- borderRadius: 7.6,
323
- zIndex: 10,
324
- borderWidth: 0,
325
- minHeight: 40
326
- }}
327
- onClick={onClickSetting}
328
- />
329
- </View>
330
- <View style={{ width: 10, height: '100%' }} />
331
- <View style={{ flex: 0.5, justifyContent: 'center' }}>
332
- <SelectDropdown
333
- defaultButtonText={t('SLA', 'SLA\'s')}
334
- data={preorderTypeList}
335
- onSelect={(selectedItem, index) => {
336
- onFiltered && onFiltered({ ...search, timeStatus: selectedItem?.key })
337
- }}
338
- buttonTextAfterSelection={(selectedItem, index) => {
339
- return selectedItem.name
340
- }}
341
- rowTextForSelection={(item, index) => {
342
- return item.key
343
- }}
344
- buttonStyle={styles.selectOption}
345
- buttonTextStyle={styles.buttonTextStyle}
346
- renderDropdownIcon={isOpened => {
347
- return <FeatherIcon name={isOpened ? 'chevron-up' : 'chevron-down'} color={'#444'} size={18} />;
348
- }}
349
- dropdownStyle={styles.dropdownStyle}
350
- dropdownOverlayColor='transparent'
351
- rowStyle={styles.rowStyle}
352
- renderCustomizedRowChild={(item, index) => {
353
- return (
354
- <SlaOption>
355
- {index !== 0 && <OrderStatus timeState={item?.key} />}
356
- <View><OText size={14} color={'#748194'} >{item?.name}</OText></View>
357
- </SlaOption>
358
- );
359
- }}
360
- />
315
+ {configState?.configs?.order_deadlines_enabled?.value === '1' && (
316
+ <View style={styles.SLAwrapper}>
317
+ <View style={{ flex: 0.5 }}>
318
+ <OButton
319
+ text={t('SLA_SETTING', 'SLA’s Settings')}
320
+ textStyle={{ color: theme.colors.backArrow }}
321
+ imgRightSrc={null}
322
+ style={{
323
+ backgroundColor: theme.colors.inputChat,
324
+ borderRadius: 7.6,
325
+ zIndex: 10,
326
+ borderWidth: 0,
327
+ minHeight: 40
328
+ }}
329
+ onClick={onClickSetting}
330
+ />
331
+ </View>
332
+ <View style={{ width: 10, height: '100%' }} />
333
+ <View style={{ flex: 0.5, justifyContent: 'center' }}>
334
+ <SelectDropdown
335
+ defaultButtonText={t('SLA', 'SLA\'s')}
336
+ data={preorderTypeList}
337
+ onSelect={(selectedItem, index) => {
338
+ onFiltered && onFiltered({ ...search, timeStatus: selectedItem?.key })
339
+ }}
340
+ buttonTextAfterSelection={(selectedItem, index) => {
341
+ return selectedItem.name
342
+ }}
343
+ rowTextForSelection={(item, index) => {
344
+ return item.key
345
+ }}
346
+ buttonStyle={styles.selectOption}
347
+ buttonTextStyle={styles.buttonTextStyle}
348
+ renderDropdownIcon={isOpened => {
349
+ return <FeatherIcon name={isOpened ? 'chevron-up' : 'chevron-down'} color={'#444'} size={18} />;
350
+ }}
351
+ dropdownStyle={styles.dropdownStyle}
352
+ dropdownOverlayColor='transparent'
353
+ rowStyle={styles.rowStyle}
354
+ renderCustomizedRowChild={(item, index) => {
355
+ return (
356
+ <SlaOption>
357
+ {index !== 0 && <OrderStatus timeState={item?.key} />}
358
+ <View><OText size={14} color={'#748194'} >{item?.name}</OText></View>
359
+ </SlaOption>
360
+ );
361
+ }}
362
+ />
363
+ </View>
361
364
  </View>
362
- </View>
365
+ )}
363
366
 
364
367
  <Sides>
365
368
  <LeftSide>
@@ -110,6 +110,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
110
110
  const theme = useTheme();
111
111
  const [, t] = useLanguage();
112
112
  const [{ parseDate }] = useUtils()
113
+ const [configState] = useConfig()
113
114
  const [orientationState] = useDeviceOrientation();
114
115
  const [, { showToast }] = useToast();
115
116
  const [openSearchModal, setOpenSearchModal] = useState(false)
@@ -439,55 +440,57 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
439
440
  />
440
441
  </IconWrapper>
441
442
  </View>
442
- <View style={styles.SLAwrapper}>
443
- <View style={{ flex: 0.5 }}>
444
- <OButton
445
- text={t('SLA_SETTING', 'SLA’s Settings')}
446
- textStyle={{ color: theme.colors.backArrow }}
447
- imgRightSrc={null}
448
- style={{
449
- backgroundColor: theme.colors.inputChat,
450
- borderRadius: 7.6,
451
- zIndex: 10,
452
- borderWidth: 0,
453
- minHeight: 40
454
- }}
455
- onClick={onClickSetting}
456
- />
457
- </View>
458
- <View style={{ width: 10, height: '100%' }} />
459
- <View style={{ flex: 0.5, justifyContent: 'center' }}>
460
- <SelectDropdown
461
- defaultButtonText={t('SLA', 'SLA\'s')}
462
- data={preorderTypeList}
463
- onSelect={(selectedItem, index) => {
464
- onFiltered && onFiltered({ ...search, timeStatus: selectedItem?.key })
465
- }}
466
- buttonTextAfterSelection={(selectedItem, index) => {
467
- return selectedItem.name
468
- }}
469
- rowTextForSelection={(item, index) => {
470
- return item.key
471
- }}
472
- buttonStyle={styles.selectOption}
473
- buttonTextStyle={styles.buttonTextStyle}
474
- renderDropdownIcon={isOpened => {
475
- return <FeatherIcon name={isOpened ? 'chevron-up' : 'chevron-down'} color={'#444'} size={18} />;
476
- }}
477
- dropdownStyle={styles.dropdownStyle}
478
- dropdownOverlayColor='transparent'
479
- rowStyle={styles.rowStyle}
480
- renderCustomizedRowChild={(item, index) => {
481
- return (
482
- <SlaOption>
483
- {index !== 0 && <OrderStatus timeState={item?.key} />}
484
- <View><OText size={14} color={'#748194'} >{item?.name}</OText></View>
485
- </SlaOption>
486
- );
487
- }}
488
- />
443
+ {configState?.configs?.order_deadlines_enabled?.value === '1' && (
444
+ <View style={styles.SLAwrapper}>
445
+ <View style={{ flex: 0.5 }}>
446
+ <OButton
447
+ text={t('SLA_SETTING', 'SLA’s Settings')}
448
+ textStyle={{ color: theme.colors.backArrow }}
449
+ imgRightSrc={null}
450
+ style={{
451
+ backgroundColor: theme.colors.inputChat,
452
+ borderRadius: 7.6,
453
+ zIndex: 10,
454
+ borderWidth: 0,
455
+ minHeight: 40
456
+ }}
457
+ onClick={onClickSetting}
458
+ />
459
+ </View>
460
+ <View style={{ width: 10, height: '100%' }} />
461
+ <View style={{ flex: 0.5, justifyContent: 'center' }}>
462
+ <SelectDropdown
463
+ defaultButtonText={t('SLA', 'SLA\'s')}
464
+ data={preorderTypeList}
465
+ onSelect={(selectedItem, index) => {
466
+ onFiltered && onFiltered({ ...search, timeStatus: selectedItem?.key })
467
+ }}
468
+ buttonTextAfterSelection={(selectedItem, index) => {
469
+ return selectedItem.name
470
+ }}
471
+ rowTextForSelection={(item, index) => {
472
+ return item.key
473
+ }}
474
+ buttonStyle={styles.selectOption}
475
+ buttonTextStyle={styles.buttonTextStyle}
476
+ renderDropdownIcon={isOpened => {
477
+ return <FeatherIcon name={isOpened ? 'chevron-up' : 'chevron-down'} color={'#444'} size={18} />;
478
+ }}
479
+ dropdownStyle={styles.dropdownStyle}
480
+ dropdownOverlayColor='transparent'
481
+ rowStyle={styles.rowStyle}
482
+ renderCustomizedRowChild={(item, index) => {
483
+ return (
484
+ <SlaOption>
485
+ {index !== 0 && <OrderStatus timeState={item?.key} />}
486
+ <View><OText size={14} color={'#748194'} >{item?.name}</OText></View>
487
+ </SlaOption>
488
+ );
489
+ }}
490
+ />
491
+ </View>
489
492
  </View>
490
- </View>
493
+ )}
491
494
  <FiltersTab>
492
495
  <ScrollView
493
496
  ref={scrollRefTab}
@@ -926,6 +929,7 @@ export const Timer = () => {
926
929
 
927
930
  export const OrdersOption = (props: OrdersOptionParams) => {
928
931
  const [, t] = useLanguage();
932
+ const [configState] = useConfig()
929
933
  const theme = useTheme()
930
934
  const ordersProps = {
931
935
  ...props,
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
2
2
  import { StyleSheet, TouchableOpacity, View, Platform, PlatformIOSStatic } from 'react-native';
3
3
  import { useTheme } from 'styled-components/native';
4
4
  import moment from 'moment'
5
- import { useLanguage, useUtils } from 'ordering-components/native';
5
+ import { useLanguage, useUtils, useConfig } from 'ordering-components/native';
6
6
  import { OButton, OIcon, OText } from '../shared';
7
7
  import {
8
8
  Card, Logo, Information, MyOrderOptions, NotificationIcon, AcceptOrRejectOrder, Timestatus
@@ -27,8 +27,14 @@ export const PreviousOrders = (props: any) => {
27
27
  } = props;
28
28
  const [, t] = useLanguage();
29
29
  const [{ parseDate, optimizeImage }] = useUtils();
30
+ const [configState] = useConfig()
30
31
  const theme = useTheme();
31
- const [currentTime, setCurrentTime] = useState()
32
+ const [, setCurrentTime] = useState()
33
+ const [allowColumns, setAllowColumns] = useState({
34
+ timer: true,
35
+ slaBar: true,
36
+ })
37
+
32
38
  const [orientationState] = useDeviceOrientation();
33
39
 
34
40
  const IS_PORTRAIT = orientationState.orientation === PORTRAIT
@@ -93,23 +99,41 @@ export const PreviousOrders = (props: any) => {
93
99
  },
94
100
  });
95
101
 
96
- const getDelayTime = (order: any) => {
102
+
103
+ const getDelayMinutes = (order: any) => {
97
104
  // targetMin = delivery_datetime + eta_time - now()
105
+ const offset = 300
106
+ const cdtToutc = parseDate(moment(order?.delivery_datetime).add(offset, 'minutes'))
98
107
  const _delivery = order?.delivery_datetime_utc
108
+ ? parseDate(order?.delivery_datetime_utc)
109
+ : parseDate(cdtToutc)
99
110
  const _eta = order?.eta_time
100
- const tagetedMin = moment(_delivery).add(_eta, 'minutes').diff(moment().utc(), 'minutes')
111
+ return moment(_delivery.replace('AM', '')).add(_eta, 'minutes').diff(moment().utc(), 'minutes')
112
+ }
113
+
114
+ const displayDelayedTime = (order: any) => {
115
+ let tagetedMin = getDelayMinutes(order)
116
+ // get day, hour and minutes
117
+ const sign = tagetedMin >= 0 ? '' : '- '
118
+ tagetedMin = Math.abs(tagetedMin)
101
119
  let day = Math.floor(tagetedMin / 1440)
102
120
  const restMinOfTargetedMin = tagetedMin - 1440 * day
103
- let restHours: any = Math.floor(restMinOfTargetedMin / 60)
104
- let restMins: any = restMinOfTargetedMin - 60 * restHours
121
+ let restHours = Math.floor(restMinOfTargetedMin / 60)
122
+ let restMins = restMinOfTargetedMin - 60 * restHours
123
+ // make standard time format
124
+ day = day === 0 ? '' : day + 'day '
125
+ restHours = restHours < 10 ? '0' + restHours : restHours
126
+ restMins = restMins < 10 ? '0' + restMins : restMins
105
127
 
106
- if (order?.time_status === 'in_time' || order?.time_status === 'at_risk') day = Math.abs(day)
107
- if (restHours < 10) restHours = ('0' + restHours)
108
- if (restMins < 10) restMins = ('0' + restMins)
109
- const finalTaget = day + 'day ' + restHours + ':' + restMins
128
+ const finalTaget = sign + day + restHours + ':' + restMins
110
129
  return finalTaget
111
130
  }
112
131
 
132
+ const getStatusClassName = (minutes: any) => {
133
+ if (isNaN(Number(minutes))) return 0
134
+ return minutes > 0 ? 'in_time' : minutes === 0 ? 'at_risk' : 'delayed'
135
+ }
136
+
113
137
  useEffect(() => {
114
138
  const interval = setInterval(() => {
115
139
  const date: any = Date.now()
@@ -119,6 +143,15 @@ export const PreviousOrders = (props: any) => {
119
143
  return () => clearInterval(interval)
120
144
  }, [])
121
145
 
146
+ useEffect(() => {
147
+ const slaSettings = configState?.configs?.order_deadlines_enabled?.value === '1'
148
+ setAllowColumns({
149
+ ...allowColumns,
150
+ timer: slaSettings,
151
+ slaBar: slaSettings
152
+ })
153
+ }, [configState.loading])
154
+
122
155
  let hash: any = {};
123
156
 
124
157
  return (
@@ -144,7 +177,9 @@ export const PreviousOrders = (props: any) => {
144
177
  activeOpacity={1}
145
178
  >
146
179
  <Card key={order.id}>
147
- <Timestatus style={{ backgroundColor: order?.time_status === 'in_time' ? '#00D27A' : order?.time_status === 'at_risk' ? '#FFC700' : order?.time_status === 'delayed' ? '#E63757' : '' }} />
180
+ {allowColumns?.slaBar && (
181
+ <Timestatus style={{ backgroundColor: getStatusClassName(getDelayMinutes(order)) === 'in_time' ? '#00D27A' : getStatusClassName(getDelayMinutes(order)) === 'at_risk' ? '#FFC700' : getStatusClassName(getDelayMinutes(order)) === 'delayed' ? '#E63757' : '' }} />
182
+ )}
148
183
  {
149
184
  order.business?.logo && (
150
185
  <Logo style={styles.logo}>
@@ -189,10 +224,10 @@ export const PreviousOrders = (props: any) => {
189
224
  ? parseDate(order?.delivery_datetime_utc, { outputFormat: 'MM/DD/YY · HH:mm a' })
190
225
  : parseDate(order?.delivery_datetime, { utc: false })}
191
226
  </OText>
192
- {(currentTabSelected === 'pending' || currentTabSelected === 'inProgress') && (
227
+ {((currentTabSelected === 'pending' || currentTabSelected === 'inProgress') && allowColumns?.timer) && (
193
228
  <>
194
229
  <OText> · </OText>
195
- <OText style={styles.date} color={order?.time_status === 'in_time' ? '#00D27A' : order?.time_status === 'at_risk' ? '#FFC700' : order?.time_status === 'delayed' ? '#E63757' : ''} >{getDelayTime(order)}</OText>
230
+ <OText style={styles.date} color={getStatusClassName(getDelayMinutes(order)) === 'in_time' ? '#00D27A' : getStatusClassName(getDelayMinutes(order)) === 'at_risk' ? '#FFC700' : getStatusClassName(getDelayMinutes(order)) === 'delayed' ? '#E63757' : ''} >{displayDelayedTime(order)}</OText>
196
231
  </>
197
232
  )}
198
233
  </View>
@@ -4,7 +4,7 @@ import { useUtils, useOrder, useLanguage } from 'ordering-components/native';
4
4
  import { useTheme } from 'styled-components/native';
5
5
  import { OIcon, OText, OModal } from '../shared';
6
6
  import { BusinessBasicInformationParams } from '../../types';
7
- import { convertHoursToMinutes } from '../../utils';
7
+ import { convertHoursToMinutes, shape } from '../../utils';
8
8
  import { BusinessInformation } from '../BusinessInformation';
9
9
  import { BusinessReviews } from '../BusinessReviews';
10
10
  import dayjs from 'dayjs';
@@ -22,6 +22,8 @@ import {
22
22
  BusinessInfoItem,
23
23
  WrapReviews,
24
24
  WrapBusinessInfo,
25
+ TitleWrapper,
26
+ RibbonBox
25
27
  } from './styles';
26
28
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
27
29
  const types = ['food', 'laundry', 'alcohol', 'groceries'];
@@ -121,9 +123,29 @@ export const BusinessBasicInformation = (
121
123
  <PlaceholderLine height={30} width={20} />
122
124
  </Placeholder>
123
125
  ) : (
124
- <OText size={24} weight={'600'}>
125
- {business?.name}
126
- </OText>
126
+ <TitleWrapper>
127
+ <OText size={24} weight={'600'}>
128
+ {business?.name}
129
+ </OText>
130
+ {business?.ribbon?.enabled && (
131
+ <RibbonBox
132
+ bgColor={business?.ribbon?.color}
133
+ isRoundRect={business?.ribbon?.shape === shape?.rectangleRound}
134
+ isCapsule={business?.ribbon?.shape === shape?.capsuleShape}
135
+ >
136
+ <OText
137
+ size={10}
138
+ weight={'400'}
139
+ color={theme.colors.white}
140
+ numberOfLines={2}
141
+ ellipsizeMode='tail'
142
+ lineHeight={13}
143
+ >
144
+ {business?.ribbon?.text}
145
+ </OText>
146
+ </RibbonBox>
147
+ )}
148
+ </TitleWrapper>
127
149
  )}
128
150
  </BusinessInfoItem>
129
151
  {loading ? (
@@ -1,4 +1,4 @@
1
- import styled from 'styled-components/native';
1
+ import styled, { css } from 'styled-components/native';
2
2
  import { Platform } from 'react-native';
3
3
 
4
4
  export const BusinessContainer = styled.View`
@@ -41,3 +41,30 @@ export const WrapBusinessInfo = styled.TouchableOpacity`
41
41
  top: 16px;
42
42
  end: 39px;
43
43
  `;
44
+
45
+ export const TitleWrapper = styled.View`
46
+ width: 100%;
47
+ flex-direction: row;
48
+ align-items: center;
49
+ justify-content: space-between;
50
+ `
51
+
52
+ export const RibbonBox = styled.View`
53
+ margin-left: 5px;
54
+ background-color: ${(props: any) => props.theme.colors.primary};
55
+ padding: 2px 8px;
56
+ max-width: 180px;
57
+ align-self: flex-start;
58
+
59
+ ${(props: any) => props.bgColor && css`
60
+ background-color: ${props.bgColor};
61
+ `}
62
+
63
+ ${(props: any) => props.isRoundRect && css`
64
+ border-radius: 7.6px;
65
+ `}
66
+
67
+ ${(props: any) => props.isCapsule && css`
68
+ border-radius: 50px;
69
+ `}
70
+ `
@@ -43,6 +43,7 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
43
43
  } = props;
44
44
  const [{ parsePrice, parseDistance, parseNumber, optimizeImage }] = useUtils();
45
45
  const [orderState] = useOrder();
46
+ const [configState] = useConfig();
46
47
  const [, t] = useLanguage();
47
48
  const theme = useTheme()
48
49
  const styles = StyleSheet.create({
@@ -135,7 +136,7 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
135
136
  </View>
136
137
  )}
137
138
  <BusinessState>
138
- {!isBusinessOpen && (
139
+ {!isBusinessOpen && (configState?.configs?.preorder_status_enabled?.value === '1') && (
139
140
  <View style={styles.businessStateView}>
140
141
  <OText
141
142
  color={theme.colors.textThird}
@@ -4,11 +4,12 @@ import { SingleProductCard } from '../SingleProductCard';
4
4
  import { NotFoundSource } from '../NotFoundSource';
5
5
  import { BusinessProductsListParams } from '../../types';
6
6
  import { OButton, OIcon, OModal, OText } from '../shared';
7
- import { ProductsContainer, ErrorMessage, WrapperNotFound } from './styles';
7
+ import { ProductsContainer, ErrorMessage, WrapperNotFound, RibbonBox } from './styles';
8
8
  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
13
 
13
14
  const BusinessProductsListUI = (props: BusinessProductsListParams) => {
14
15
  const {
@@ -110,6 +111,24 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
110
111
  <OText size={16} weight="600">
111
112
  {category.name}
112
113
  </OText>
114
+ {category?.ribbon?.enabled && (
115
+ <RibbonBox
116
+ bgColor={category?.ribbon?.color}
117
+ isRoundRect={category?.ribbon?.shape === shape?.rectangleRound}
118
+ isCapsule={category?.ribbon?.shape === shape?.capsuleShape}
119
+ >
120
+ <OText
121
+ size={10}
122
+ weight={'400'}
123
+ color={theme.colors.white}
124
+ numberOfLines={2}
125
+ ellipsizeMode='tail'
126
+ lineHeight={13}
127
+ >
128
+ {category?.ribbon?.text}
129
+ </OText>
130
+ </RibbonBox>
131
+ )}
113
132
  </View>
114
133
  {!!category?.description && (
115
134
  <View style={{ position: 'relative' }}>
@@ -1,4 +1,4 @@
1
- import styled from 'styled-components/native'
1
+ import styled, { css } from 'styled-components/native'
2
2
 
3
3
  export const ProductsContainer = styled.View`
4
4
  `
@@ -11,4 +11,23 @@ export const ErrorMessage = styled.View`
11
11
 
12
12
  export const WrapperNotFound = styled.View`
13
13
  height: 500px;
14
+ `
15
+
16
+ export const RibbonBox = styled.View`
17
+ margin-left: 5px;
18
+ background-color: ${(props: any) => props.theme.colors.primary};
19
+ padding: 2px 8px;
20
+ max-width: 180px;
21
+
22
+ ${(props: any) => props.bgColor && css`
23
+ background-color: ${props.bgColor};
24
+ `}
25
+
26
+ ${(props: any) => props.isRoundRect && css`
27
+ border-radius: 7.6px;
28
+ `}
29
+
30
+ ${(props: any) => props.isCapsule && css`
31
+ border-radius: 50px;
32
+ `}
14
33
  `
@@ -202,7 +202,7 @@ const OrderSummaryUI = (props: any) => {
202
202
  <OSRow>
203
203
  <OText size={12} numberOfLines={1}>
204
204
  {fee.name || t('INHERIT_FROM_BUSINESS', 'Inherit from business')}{' '}
205
- ({parsePrice(fee?.fixed)} + {fee?.percentage}%){' '}
205
+ ({fee?.fixed > 0 && `${parsePrice(fee?.fixed)} + `}{fee.percentage}%)
206
206
  </OText>
207
207
  <TouchableOpacity onPress={() => setOpenTaxModal({ open: true, data: fee, type: 'fee' })} >
208
208
  <AntIcon name='infocirlceo' size={16} color={theme.colors.primary} />
@@ -7,10 +7,11 @@ import {
7
7
  } from 'ordering-components/native';
8
8
  import { useTheme } from 'styled-components/native';
9
9
  import { SingleProductCardParams } from '../../types';
10
- import { CardContainer, CardInfo, SoldOut, QuantityContainer, PricesContainer } from './styles';
10
+ import { CardContainer, CardInfo, SoldOut, QuantityContainer, PricesContainer, RibbonBox, LogoWrapper } from './styles';
11
11
  import { StyleSheet } from 'react-native';
12
12
  import { OText, OIcon } from '../shared';
13
13
  import FastImage from 'react-native-fast-image'
14
+ import { shape } from '../../utils';
14
15
 
15
16
  export const SingleProductCard = (props: SingleProductCardParams) => {
16
17
  const {
@@ -46,8 +47,7 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
46
47
  productStyle: {
47
48
  width: 75,
48
49
  height: 75,
49
- borderRadius: 7.6,
50
- marginStart: 12
50
+ borderRadius: 7.6
51
51
  },
52
52
  quantityContainer: {
53
53
  position: 'absolute',
@@ -136,21 +136,42 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
136
136
  {product?.description}
137
137
  </OText>
138
138
  </CardInfo>
139
- {product?.images ? (
140
- <FastImage
141
- style={styles.productStyle}
142
- source={{
143
- uri: optimizeImage(product?.images, 'h_250,c_limit'),
144
- priority: FastImage.priority.normal,
145
- }}
146
- resizeMode={FastImage.resizeMode.cover}
147
- />
148
- ) : (
149
- <OIcon
150
- src={theme?.images?.dummies?.product}
151
- style={styles.productStyle}
152
- />
153
- )}
139
+ <LogoWrapper>
140
+ {product?.ribbon?.enabled && (
141
+ <RibbonBox
142
+ bgColor={product?.ribbon?.color}
143
+ isRoundRect={product?.ribbon?.shape === shape?.rectangleRound}
144
+ isCapsule={product?.ribbon?.shape === shape?.capsuleShape}
145
+ >
146
+ <OText
147
+ size={10}
148
+ weight={'400'}
149
+ color={theme.colors.white}
150
+ numberOfLines={2}
151
+ ellipsizeMode='tail'
152
+ lineHeight={13}
153
+ >
154
+ {product?.ribbon?.text}
155
+ </OText>
156
+ </RibbonBox>
157
+ )}
158
+ {product?.images ? (
159
+ <FastImage
160
+ style={styles.productStyle}
161
+ source={{
162
+ uri: optimizeImage(product?.images, 'h_250,c_limit'),
163
+ priority: FastImage.priority.normal,
164
+ }}
165
+ resizeMode={FastImage.resizeMode.cover}
166
+ />
167
+ ) : (
168
+ <OIcon
169
+ src={theme?.images?.dummies?.product}
170
+ style={styles.productStyle}
171
+ />
172
+ )}
173
+ </LogoWrapper>
174
+
154
175
  {(isSoldOut || maxProductQuantity <= 0) && (
155
176
  <SoldOut>
156
177
  <OText size={12} weight="bold" color={theme.colors.textSecondary} style={styles.soldOutTextStyle}>
@@ -1,4 +1,4 @@
1
- import styled from 'styled-components/native'
1
+ import styled, { css } from 'styled-components/native'
2
2
 
3
3
  export const CardContainer = styled.TouchableOpacity`
4
4
  flex: 1;
@@ -31,3 +31,30 @@ export const PricesContainer = styled.View`
31
31
  flex-direction: row;
32
32
  align-items: center;
33
33
  `
34
+
35
+ export const LogoWrapper = styled.View`
36
+ position: relative;
37
+ margin-left: 12px;
38
+ `
39
+
40
+ export const RibbonBox = styled.View`
41
+ position: absolute;
42
+ z-index: 1;
43
+ top: -4px;
44
+ right: -4px;
45
+ background-color: ${(props: any) => props.theme.colors.primary};
46
+ padding: 1px 8px;
47
+ max-width: 60px;
48
+
49
+ ${(props: any) => props.bgColor && css`
50
+ background-color: ${props.bgColor};
51
+ `}
52
+
53
+ ${(props: any) => props.isRoundRect && css`
54
+ border-radius: 7.6px;
55
+ `}
56
+
57
+ ${(props: any) => props.isCapsule && css`
58
+ border-radius: 50px;
59
+ `}
60
+ `
@@ -170,6 +170,15 @@ export const getTypesText = (value: number) => {
170
170
  return ret?.content;
171
171
  }
172
172
 
173
+ /**
174
+ * List shape for ribbon
175
+ */
176
+ export const shape = {
177
+ rectangle: 'rectangle',
178
+ rectangleRound: 'rectangle_round',
179
+ capsuleShape: 'capsule_shape'
180
+ }
181
+
173
182
  /**
174
183
  * Function to transform degree to radian
175
184
  * @param {number} value for transform