react-native-chatbot-ai 0.1.53 → 0.1.54

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 (87) hide show
  1. package/lib/module/assets/images/img_empty_data.png +0 -0
  2. package/lib/module/assets/images/index.js +2 -1
  3. package/lib/module/assets/images/index.js.map +1 -1
  4. package/lib/module/components/Drawer/SessionList.js +2 -1
  5. package/lib/module/components/Drawer/SessionList.js.map +1 -1
  6. package/lib/module/components/chat/ChatMessageList.js +15 -2
  7. package/lib/module/components/chat/ChatMessageList.js.map +1 -1
  8. package/lib/module/components/chat/ChatProductList.js +77 -0
  9. package/lib/module/components/chat/ChatProductList.js.map +1 -0
  10. package/lib/module/components/chat/index.js +134 -4
  11. package/lib/module/components/chat/index.js.map +1 -1
  12. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js +0 -2
  13. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js.map +1 -1
  14. package/lib/module/components/chat/item/ChatTable.js +19 -24
  15. package/lib/module/components/chat/item/ChatTable.js.map +1 -1
  16. package/lib/module/components/product/Card.js +226 -177
  17. package/lib/module/components/product/Card.js.map +1 -1
  18. package/lib/module/components/product/CardHorizontal.js +17 -13
  19. package/lib/module/components/product/CardHorizontal.js.map +1 -1
  20. package/lib/module/constants/events.js +2 -1
  21. package/lib/module/constants/events.js.map +1 -1
  22. package/lib/module/constants/query.js +2 -1
  23. package/lib/module/constants/query.js.map +1 -1
  24. package/lib/module/context/ChatContext.js +13 -3
  25. package/lib/module/context/ChatContext.js.map +1 -1
  26. package/lib/module/hooks/message/useMessage.js +7 -1
  27. package/lib/module/hooks/message/useMessage.js.map +1 -1
  28. package/lib/module/hooks/message/useSendMessage.js +3 -1
  29. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  30. package/lib/module/hooks/session/useGetExternalSessionInfo.js +17 -0
  31. package/lib/module/hooks/session/useGetExternalSessionInfo.js.map +1 -0
  32. package/lib/module/services/endpoints.js +2 -1
  33. package/lib/module/services/endpoints.js.map +1 -1
  34. package/lib/module/translation/resources/i18n.js +7 -1
  35. package/lib/module/translation/resources/i18n.js.map +1 -1
  36. package/lib/module/types/chat.js.map +1 -1
  37. package/lib/typescript/src/assets/images/index.d.ts +1 -0
  38. package/lib/typescript/src/assets/images/index.d.ts.map +1 -1
  39. package/lib/typescript/src/components/Drawer/SessionList.d.ts.map +1 -1
  40. package/lib/typescript/src/components/chat/ChatMessageList.d.ts.map +1 -1
  41. package/lib/typescript/src/components/chat/ChatProductList.d.ts +7 -0
  42. package/lib/typescript/src/components/chat/ChatProductList.d.ts.map +1 -0
  43. package/lib/typescript/src/components/chat/index.d.ts.map +1 -1
  44. package/lib/typescript/src/components/chat/item/ChatAIAnswerMessageItem.d.ts.map +1 -1
  45. package/lib/typescript/src/components/chat/item/ChatTable.d.ts.map +1 -1
  46. package/lib/typescript/src/components/product/Card.d.ts +6 -0
  47. package/lib/typescript/src/components/product/Card.d.ts.map +1 -1
  48. package/lib/typescript/src/components/product/CardHorizontal.d.ts +1 -0
  49. package/lib/typescript/src/components/product/CardHorizontal.d.ts.map +1 -1
  50. package/lib/typescript/src/constants/events.d.ts +1 -0
  51. package/lib/typescript/src/constants/events.d.ts.map +1 -1
  52. package/lib/typescript/src/constants/query.d.ts +1 -0
  53. package/lib/typescript/src/constants/query.d.ts.map +1 -1
  54. package/lib/typescript/src/context/ChatContext.d.ts.map +1 -1
  55. package/lib/typescript/src/hooks/message/useMessage.d.ts.map +1 -1
  56. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  57. package/lib/typescript/src/hooks/session/useGetExternalSessionInfo.d.ts +6 -0
  58. package/lib/typescript/src/hooks/session/useGetExternalSessionInfo.d.ts.map +1 -0
  59. package/lib/typescript/src/services/endpoints.d.ts +1 -0
  60. package/lib/typescript/src/services/endpoints.d.ts.map +1 -1
  61. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  62. package/lib/typescript/src/types/chat.d.ts +2 -0
  63. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  64. package/lib/typescript/src/types/dto.d.ts +10 -0
  65. package/lib/typescript/src/types/dto.d.ts.map +1 -1
  66. package/package.json +6 -2
  67. package/src/assets/images/img_empty_data.png +0 -0
  68. package/src/assets/images/index.ts +1 -0
  69. package/src/components/Drawer/SessionList.tsx +4 -2
  70. package/src/components/chat/ChatMessageList.tsx +20 -2
  71. package/src/components/chat/ChatProductList.tsx +92 -0
  72. package/src/components/chat/index.tsx +145 -2
  73. package/src/components/chat/item/ChatAIAnswerMessageItem.tsx +0 -2
  74. package/src/components/chat/item/ChatTable.tsx +17 -29
  75. package/src/components/product/Card.tsx +228 -173
  76. package/src/components/product/CardHorizontal.tsx +19 -15
  77. package/src/constants/events.ts +1 -0
  78. package/src/constants/query.ts +1 -0
  79. package/src/context/ChatContext.tsx +13 -1
  80. package/src/hooks/message/useMessage.ts +7 -1
  81. package/src/hooks/message/useSendMessage.ts +3 -1
  82. package/src/hooks/session/useGetExternalSessionInfo.ts +23 -0
  83. package/src/ignore.d.ts +1 -0
  84. package/src/services/endpoints.ts +2 -0
  85. package/src/translation/resources/i18n.ts +7 -0
  86. package/src/types/chat.ts +2 -0
  87. package/src/types/dto.ts +12 -0
@@ -27,11 +27,18 @@ interface IProductCardProps {
27
27
  messageId?: string;
28
28
  index?: number;
29
29
  showSensitiveInfo?: boolean;
30
+ data?: IProductItem;
31
+ onJumToMessage?: () => void;
32
+ wrapperStyle?: any;
33
+ showFavorite?: boolean;
30
34
  }
31
35
 
32
36
  const ProductCardWrapper = memo((props: IProductCardProps) => {
33
- const { productId } = props;
34
- const item = useProductsStore((state) => state.products[productId || '']);
37
+ const { productId, data } = props;
38
+ const fetchProduct = useProductsStore(
39
+ (state) => state.products[productId || '']
40
+ );
41
+ const item = data || fetchProduct;
35
42
 
36
43
  if (!item) {
37
44
  return null;
@@ -41,7 +48,7 @@ const ProductCardWrapper = memo((props: IProductCardProps) => {
41
48
  });
42
49
  ProductCardWrapper.displayName = 'ProductCardWrapper';
43
50
 
44
- const PRODUCT_WIDTH =
51
+ export const PRODUCT_VERTICAL_WIDTH =
45
52
  (KDims.width - KSpacingValue['2rem'] - KSpacingValue['0.75rem']) / 2;
46
53
 
47
54
  const ProductCard = memo(
@@ -49,7 +56,10 @@ const ProductCard = memo(
49
56
  item,
50
57
  messageId,
51
58
  index,
52
- showSensitiveInfo = true,
59
+ showSensitiveInfo = false,
60
+ onJumToMessage,
61
+ wrapperStyle,
62
+ showFavorite = false,
53
63
  }: IProductCardProps & { item: IProductItem }) => {
54
64
  const onAddToCart = useChatContext()?.onAddToCart;
55
65
  const onBuyNow = useChatContext()?.onBuyNow;
@@ -214,194 +224,218 @@ const ProductCard = memo(
214
224
  }, [onBuyNow, logGA, item, messageId]);
215
225
 
216
226
  return (
217
- <KContainer.Touchable style={styles.container} onPress={onPress}>
218
- <KContainer.View style={styles.image}>
219
- <KImage.Base
220
- uri={imageUrl}
221
- size={PRODUCT_WIDTH - 2} // subtract border width
222
- flashListForceRenderKey={id}
223
- brTL="2x"
224
- brTR="2x"
225
- />
226
- <KContainer.View style={styles.favoriteContainer}>
227
- <KButton.Base
228
- onPress={() => {}}
229
- size="sm"
230
- icon={{
231
- vectorName: isFavorite ? 'heart-b' : 'heart-o',
232
- size: 16,
233
- tintColor: isFavorite
234
- ? KColors.danger.normal
235
- : KColors.gray.normal,
236
- }}
237
- br="round"
238
- background={KColors.hexToRgba(KColors.white, 0.9)}
227
+ <KContainer.View style={[styles.wrapper, wrapperStyle && wrapperStyle]}>
228
+ <KContainer.Touchable style={styles.container} onPress={onPress}>
229
+ <KContainer.View style={styles.image}>
230
+ <KImage.Base
231
+ uri={imageUrl}
232
+ size={PRODUCT_VERTICAL_WIDTH - 2} // subtract border width
233
+ flashListForceRenderKey={id}
234
+ brTL="2x"
235
+ brTR="2x"
239
236
  />
240
- </KContainer.View>
241
- <KContainer.VisibleView visible={showPriceDiscount}>
242
- <KContainer.View style={styles.discountContainer} row brBR="2x">
243
- <KContainer.VisibleView visible={showPriceDiscount}>
244
- <KContainer.View
245
- background={KColors.palette.danger.w400}
246
- paddingH={'0.5rem'}
247
- paddingV={'0.25rem'}
248
- id="price discount"
249
- brBR={'2x'}
250
- >
251
- <KLabel.Text typo="Text2XsBold" color={KColors.white}>
252
- {`-${discountPercentage}%`}
253
- </KLabel.Text>
254
- </KContainer.View>
255
- </KContainer.VisibleView>
256
- </KContainer.View>
257
- </KContainer.VisibleView>
258
- <KContainer.VisibleView visible={mVouchers.length > 0}>
259
- <KContainer.View row style={styles.voucherContainer} id="promotion">
260
- {mVouchers.map((i: any, idx: number) => {
261
- const isLast = idx === vouchers.length - 1;
262
- return (
263
- <KProduct.PromotionTag
264
- key={i.id}
265
- type={i.type as any}
266
- discount={i.discount}
267
- isFree={
268
- i.type === 'SHIPPING_FEE' && i.resultType === 'FREE'
269
- }
270
- brTR={isLast ? '2x' : undefined}
271
- />
272
- );
273
- })}
274
- </KContainer.View>
275
- </KContainer.VisibleView>
276
- <KContainer.VisibleView visible={isSuspended}>
277
- <KContainer.View style={styles.abs}>
278
- <KLabel.Text
279
- typo="TextXsBold"
280
- color={KColors.palette.gray.w50}
281
- textAlign
282
- >
283
- {'Tạm ngừng kinh doanh'}
284
- </KLabel.Text>
285
- </KContainer.View>
286
- </KContainer.VisibleView>
287
- <KContainer.VisibleView visible={isSoldOut}>
288
- <KContainer.View style={styles.abs}>
289
- <KLabel.Text
290
- typo="TextXsBold"
291
- color={KColors.palette.gray.w50}
292
- textAlign
293
- >
294
- {'Hết hàng'}
295
- </KLabel.Text>
296
- </KContainer.View>
297
- </KContainer.VisibleView>
298
- </KContainer.View>
299
-
300
- <KContainer.View style={styles.contentContainer}>
301
- <KLabel.Text typo="TextSmMedium" numberOfLines={2}>
302
- {name}
303
- </KLabel.Text>
237
+ <KContainer.VisibleView visible={showFavorite}>
238
+ <KContainer.View style={styles.favoriteContainer}>
239
+ <KButton.Base
240
+ onPress={() => {}}
241
+ size="sm"
242
+ icon={{
243
+ vectorName: isFavorite ? 'heart-b' : 'heart-o',
244
+ size: 16,
245
+ tintColor: isFavorite
246
+ ? KColors.danger.normal
247
+ : KColors.gray.normal,
248
+ }}
249
+ br="round"
250
+ background={KColors.hexToRgba(KColors.white, 0.9)}
251
+ />
252
+ </KContainer.View>
253
+ </KContainer.VisibleView>
304
254
 
305
- <KContainer.VisibleView visible={showSensitiveInfo}>
306
- <KContainer.View style={styles.sensitiveInfo}>
307
- <KContainer.View row alignItems>
255
+ <KContainer.VisibleView visible={showPriceDiscount}>
256
+ <KContainer.View style={styles.discountContainer} row brBR="2x">
257
+ <KContainer.VisibleView visible={showPriceDiscount}>
258
+ <KContainer.View
259
+ background={KColors.palette.danger.w400}
260
+ paddingH={'0.5rem'}
261
+ paddingV={'0.25rem'}
262
+ id="price discount"
263
+ brBR={'2x'}
264
+ >
265
+ <KLabel.Text typo="Text2XsBold" color={KColors.white}>
266
+ {`-${discountPercentage}%`}
267
+ </KLabel.Text>
268
+ </KContainer.View>
269
+ </KContainer.VisibleView>
270
+ </KContainer.View>
271
+ </KContainer.VisibleView>
272
+ <KContainer.VisibleView visible={mVouchers.length > 0}>
273
+ <KContainer.View
274
+ row
275
+ style={styles.voucherContainer}
276
+ id="promotion"
277
+ >
278
+ {mVouchers.map((i: any, idx: number) => {
279
+ const isLast = idx === vouchers.length - 1;
280
+ return (
281
+ <KProduct.PromotionTag
282
+ key={i.id}
283
+ type={i.type as any}
284
+ discount={i.discount}
285
+ isFree={
286
+ i.type === 'SHIPPING_FEE' && i.resultType === 'FREE'
287
+ }
288
+ brTR={isLast ? '2x' : undefined}
289
+ />
290
+ );
291
+ })}
292
+ </KContainer.View>
293
+ </KContainer.VisibleView>
294
+ <KContainer.VisibleView visible={isSuspended}>
295
+ <KContainer.View style={styles.abs}>
308
296
  <KLabel.Text
309
- typo="TextXsNormal"
310
- color={KColors.secondary.normal}
297
+ typo="TextXsBold"
298
+ color={KColors.palette.gray.w50}
299
+ textAlign
311
300
  >
312
- {trans('commissions')}
301
+ {'Tạm ngừng kinh doanh'}
302
+ </KLabel.Text>
303
+ </KContainer.View>
304
+ </KContainer.VisibleView>
305
+ <KContainer.VisibleView visible={isSoldOut}>
306
+ <KContainer.View style={styles.abs}>
307
+ <KLabel.Text
308
+ typo="TextXsBold"
309
+ color={KColors.palette.gray.w50}
310
+ textAlign
311
+ >
312
+ {'Hết hàng'}
313
+ </KLabel.Text>
314
+ </KContainer.View>
315
+ </KContainer.VisibleView>
316
+ </KContainer.View>
317
+
318
+ <KContainer.View style={styles.contentContainer}>
319
+ <KLabel.Text typo="TextSmMedium" numberOfLines={2}>
320
+ {name}
321
+ </KLabel.Text>
322
+
323
+ <KContainer.VisibleView visible={showSensitiveInfo}>
324
+ <KContainer.View style={styles.sensitiveInfo}>
325
+ <KContainer.View row alignItems>
313
326
  <KLabel.Text
314
- typo="TextXsBold"
327
+ typo="TextXsNormal"
315
328
  color={KColors.secondary.normal}
316
329
  >
317
- {minPriceByDiscountTxt}
330
+ {trans('commissions')}
331
+ <KLabel.Text
332
+ typo="TextXsBold"
333
+ color={KColors.secondary.normal}
334
+ >
335
+ {minPriceByDiscountTxt}
336
+ </KLabel.Text>
318
337
  </KLabel.Text>
338
+ <KLabel.Text
339
+ marginL={'0.25rem'}
340
+ style={styles.labelLineThrough}
341
+ typo="Text2XsNormal"
342
+ color={KColors.gray.light}
343
+ numberOfLines={1}
344
+ flex
345
+ >
346
+ {minOriginalPriceByDiscountTxt}
347
+ </KLabel.Text>
348
+ </KContainer.View>
349
+ <KLabel.Text typo="TextXsNormal" color={KColors.gray.normal}>
350
+ {`${trans('points')}${PTManager.number.numberWithCommas(minBP || 0)}`}
319
351
  </KLabel.Text>
352
+ </KContainer.View>
353
+ </KContainer.VisibleView>
354
+
355
+ <KContainer.View style={styles.priceContainer}>
356
+ <KLabel.Text
357
+ typo="TextNmBold"
358
+ color={KColors.palette.customer.w400}
359
+ >
360
+ {PTManager.number.formatCurrency(minPrice)}
361
+ </KLabel.Text>
362
+ <KContainer.VisibleView visible={showPriceDiscount}>
320
363
  <KLabel.Text
321
- marginL={'0.25rem'}
322
364
  style={styles.labelLineThrough}
323
365
  typo="Text2XsNormal"
324
366
  color={KColors.gray.light}
325
367
  numberOfLines={1}
326
368
  flex
327
369
  >
328
- {minOriginalPriceByDiscountTxt}
370
+ {originalPriceText}
329
371
  </KLabel.Text>
330
- </KContainer.View>
331
- <KLabel.Text typo="TextXsNormal" color={KColors.gray.normal}>
332
- {`${trans('points')}${PTManager.number.numberWithCommas(minBP || 0)}`}
333
- </KLabel.Text>
372
+ </KContainer.VisibleView>
334
373
  </KContainer.View>
335
- </KContainer.VisibleView>
336
-
337
- <KContainer.View style={styles.priceContainer}>
338
- <KLabel.Text
339
- typo="TextNmBold"
340
- color={KColors.palette.customer.w400}
341
- >
342
- {PTManager.number.formatCurrency(minPrice)}
343
- </KLabel.Text>
344
- <KContainer.VisibleView visible={showPriceDiscount}>
345
- <KLabel.Text
346
- style={styles.labelLineThrough}
347
- typo="Text2XsNormal"
348
- color={KColors.gray.light}
349
- numberOfLines={1}
350
- flex
351
- >
352
- {originalPriceText}
353
- </KLabel.Text>
354
- </KContainer.VisibleView>
355
- </KContainer.View>
356
374
 
357
- <KContainer.View style={styles.saleRow}>
358
- <KContainer.View style={styles.ratingContainer}>
359
- <KRating.Star point={5} size="x-small" />
360
- <KLabel.Text typo="TextXsNormal" color={KColors.gray.light}>
361
- {`${avgRating?.toFixed(1) || 0} (${totalRating || 0})`}
362
- </KLabel.Text>
363
- <KContainer.View height={12}>
364
- <KDivider
365
- vertical
366
- type="line"
367
- background={KColors.border.light}
368
- size="xs"
369
- />
375
+ <KContainer.View style={styles.saleRow}>
376
+ <KContainer.View style={styles.ratingContainer}>
377
+ <KRating.Star point={5} size="x-small" />
378
+ <KLabel.Text typo="TextXsNormal" color={KColors.gray.light}>
379
+ {`${avgRating?.toFixed(1) || 0} (${totalRating || 0})`}
380
+ </KLabel.Text>
381
+ <KContainer.View height={12}>
382
+ <KDivider
383
+ vertical
384
+ type="line"
385
+ background={KColors.border.light}
386
+ size="xs"
387
+ />
388
+ </KContainer.View>
389
+ <KLabel.Text
390
+ flex
391
+ numberOfLines={1}
392
+ typo="TextXsNormal"
393
+ color={KColors.gray.normal}
394
+ >
395
+ {totalSoldTxt}
396
+ </KLabel.Text>
370
397
  </KContainer.View>
371
- <KLabel.Text
372
- flex
373
- numberOfLines={1}
374
- typo="TextXsNormal"
375
- color={KColors.gray.normal}
376
- >
377
- {totalSoldTxt}
378
- </KLabel.Text>
379
398
  </KContainer.View>
380
- </KContainer.View>
381
399
 
382
- <KContainer.View style={styles.actionContainer}>
383
- <KButton.Base
384
- onPress={onPressAddToCart}
385
- background={KColors.palette.primary.w25}
386
- tintColor={KColors.primary.normal}
387
- icon={{
388
- vectorName: 'cart-plus-o',
389
- size: 16,
390
- }}
391
- size="sm"
392
- disabled={!isEnabledAddToCart}
393
- />
394
- <KButton.Solid
395
- onPress={onPressBuyNow}
396
- size="sm"
397
- label="Mua ngay"
398
- kind="primary"
399
- disabled={!isEnabledBuyNow}
400
- enhanceStyle={styles.buttonBuyNow}
401
- />
400
+ <KContainer.View style={styles.actionContainer}>
401
+ <KButton.Base
402
+ onPress={onPressAddToCart}
403
+ background={KColors.palette.primary.w25}
404
+ tintColor={KColors.primary.normal}
405
+ icon={{
406
+ vectorName: 'cart-plus-o',
407
+ size: 16,
408
+ }}
409
+ size="sm"
410
+ disabled={!isEnabledAddToCart}
411
+ />
412
+ <KButton.Solid
413
+ onPress={onPressBuyNow}
414
+ size="sm"
415
+ label="Mua ngay"
416
+ kind="primary"
417
+ disabled={!isEnabledBuyNow}
418
+ enhanceStyle={styles.buttonBuyNow}
419
+ />
420
+ </KContainer.View>
402
421
  </KContainer.View>
403
- </KContainer.View>
404
- </KContainer.Touchable>
422
+ </KContainer.Touchable>
423
+ <KContainer.VisibleView visible={!!onJumToMessage}>
424
+ <KContainer.Touchable
425
+ style={styles.jumpToMessageContainer}
426
+ onPress={onJumToMessage}
427
+ >
428
+ <KLabel.Text typo="TextSmNormal" color={KColors.gray.dark}>
429
+ {trans('view_original_message')}
430
+ </KLabel.Text>
431
+ <KImage.VectorIcons
432
+ name="arrow-right-o"
433
+ size={16}
434
+ color={KColors.gray.dark}
435
+ />
436
+ </KContainer.Touchable>
437
+ </KContainer.VisibleView>
438
+ </KContainer.View>
405
439
  );
406
440
  }
407
441
  );
@@ -411,17 +445,28 @@ ProductCard.displayName = 'ProductCard';
411
445
  export default ProductCardWrapper;
412
446
 
413
447
  const styles = StyleSheet.create({
448
+ wrapper: {
449
+ width: PRODUCT_VERTICAL_WIDTH,
450
+ borderRadius: KRadiusValue['2x'],
451
+ backgroundColor: KColors.opacity.gray[10],
452
+ },
414
453
  container: {
415
454
  borderRadius: KRadiusValue['2x'],
416
455
  borderWidth: 1,
417
456
  borderColor: KColors.hexToRgba(KColors.gray.dark, 0.2),
418
- width: PRODUCT_WIDTH,
457
+ width: PRODUCT_VERTICAL_WIDTH,
419
458
  backgroundColor: KColors.white,
459
+
460
+ shadowColor: 'rgba(14, 28, 52, 0.1)',
461
+ shadowOffset: { width: 0, height: 2 },
462
+ shadowOpacity: 1,
463
+ shadowRadius: 12,
464
+ elevation: 6,
420
465
  },
421
466
  image: {
422
467
  position: 'relative',
423
- width: PRODUCT_WIDTH - 2, // border width
424
- height: PRODUCT_WIDTH - 2, // border width
468
+ width: PRODUCT_VERTICAL_WIDTH - 2, // border width
469
+ height: PRODUCT_VERTICAL_WIDTH - 2, // border width
425
470
  },
426
471
  favoriteContainer: {
427
472
  position: 'absolute',
@@ -443,7 +488,8 @@ const styles = StyleSheet.create({
443
488
  alignItems: 'center',
444
489
  padding: KSpacingValue['1rem'],
445
490
  backgroundColor: KColors.hexToRgba(KColors.black, 0.5),
446
- borderRadius: KRadiusValue['2x'],
491
+ borderTopLeftRadius: KRadiusValue['2x'],
492
+ borderTopRightRadius: KRadiusValue['2x'],
447
493
  ...StyleSheet.absoluteFillObject,
448
494
  },
449
495
  contentContainer: {
@@ -481,4 +527,13 @@ const styles = StyleSheet.create({
481
527
  buttonBuyNow: {
482
528
  flex: 1,
483
529
  },
530
+ jumpToMessageContainer: {
531
+ paddingHorizontal: KSpacingValue['0.75rem'],
532
+ paddingTop: 10,
533
+ paddingBottom: KSpacingValue['0.5rem'],
534
+ flexDirection: 'row',
535
+ alignItems: 'center',
536
+ justifyContent: 'center',
537
+ gap: KSpacingValue['0.25rem'],
538
+ },
484
539
  });
@@ -24,6 +24,7 @@ interface IProductHorizontalCardProps {
24
24
  productId?: string;
25
25
  messageId?: string;
26
26
  index?: number;
27
+ showFavorite?: boolean;
27
28
  }
28
29
 
29
30
  const ProductHorizontalCardWrapper = memo(
@@ -45,6 +46,7 @@ const ProductHorizontalCard = memo(
45
46
  item,
46
47
  messageId,
47
48
  index,
49
+ showFavorite = false,
48
50
  }: IProductHorizontalCardProps & { item: IProductItem }) => {
49
51
  const onAddToCart = useChatContext()?.onAddToCart;
50
52
  const onBuyNow = useChatContext()?.onBuyNow;
@@ -195,21 +197,23 @@ const ProductHorizontalCard = memo(
195
197
  br="2x"
196
198
  flashListForceRenderKey={id}
197
199
  />
198
- <KContainer.View style={styles.favoriteContainer}>
199
- <KButton.Base
200
- onPress={() => {}}
201
- size="xs"
202
- icon={{
203
- vectorName: isFavorite ? 'heart-b' : 'heart-o',
204
- size: 14,
205
- tintColor: isFavorite
206
- ? KColors.danger.normal
207
- : KColors.gray.normal,
208
- }}
209
- br="round"
210
- background={KColors.hexToRgba(KColors.white, 0.9)}
211
- />
212
- </KContainer.View>
200
+ <KContainer.VisibleView visible={showFavorite}>
201
+ <KContainer.View style={styles.favoriteContainer}>
202
+ <KButton.Base
203
+ onPress={() => {}}
204
+ size="xs"
205
+ icon={{
206
+ vectorName: isFavorite ? 'heart-b' : 'heart-o',
207
+ size: 14,
208
+ tintColor: isFavorite
209
+ ? KColors.danger.normal
210
+ : KColors.gray.normal,
211
+ }}
212
+ br="round"
213
+ background={KColors.hexToRgba(KColors.white, 0.9)}
214
+ />
215
+ </KContainer.View>
216
+ </KContainer.VisibleView>
213
217
  <KContainer.VisibleView visible={isSuspended}>
214
218
  <KContainer.View style={styles.abs}>
215
219
  <KLabel.Text
@@ -3,6 +3,7 @@ export const events = {
3
3
  updateMultipleMessage: 'update_multiple_message',
4
4
  forceUpdateMessages: 'force_update_messages',
5
5
  updateMessageError: 'update_message_error',
6
+ scrollToMessage: 'scroll_to_message',
6
7
  };
7
8
 
8
9
  export const GAEvents = {
@@ -8,4 +8,5 @@ export const QUERY_KEYS = {
8
8
  SHARE_SESSION: 'SHARE_SESSION',
9
9
  DELETE_SESSION: 'DELETE_SESSION',
10
10
  SEND_FEEDBACK: 'SEND_FEEDBACK',
11
+ GET_EXTERNAL_SESSION_INFO: 'GET_EXTERNAL_SESSION_INFO',
11
12
  };
@@ -1,8 +1,9 @@
1
- import { createContext, useContext, useRef } from 'react';
1
+ import { createContext, useContext, useEffect, useRef, useState } from 'react';
2
2
  import type { ChatContextType, ChatProviderProps } from '../types/chat';
3
3
  import ChatBotAI from '../components/chat';
4
4
  import Portal from '../components/portal';
5
5
  import ReanimatedDrawerExample from '../components/Drawer';
6
+ import useSessionStore from '../store/session';
6
7
 
7
8
  export const ChatContext = createContext<ChatContextType>({
8
9
  apiAddress: '',
@@ -18,12 +19,17 @@ export const ChatContext = createContext<ChatContextType>({
18
19
  chatbotUrl: '',
19
20
  logGA: () => {},
20
21
  notifyError: () => {},
22
+ tabIndex: 0,
23
+ setTabIndex: () => {},
21
24
  });
22
25
 
23
26
  export const useChatContext = () => useContext(ChatContext);
24
27
 
25
28
  export const ChatProvider = (props: ChatProviderProps) => {
26
29
  const ref = useRef<any>(null);
30
+ const [tabIndex, setTabIndex] = useState(0);
31
+ const sessionId = useSessionStore((state) => state.sessionId);
32
+
27
33
  const openDrawer = () => {
28
34
  ref.current?.openDrawer();
29
35
  };
@@ -46,6 +52,10 @@ export const ChatProvider = (props: ChatProviderProps) => {
46
52
  notifyError,
47
53
  } = props;
48
54
 
55
+ useEffect(() => {
56
+ setTabIndex(0);
57
+ }, [sessionId]);
58
+
49
59
  return (
50
60
  <ChatContext.Provider
51
61
  value={{
@@ -63,6 +73,8 @@ export const ChatProvider = (props: ChatProviderProps) => {
63
73
  chatbotUrl,
64
74
  logGA,
65
75
  notifyError,
76
+ tabIndex,
77
+ setTabIndex,
66
78
  }}
67
79
  >
68
80
  <ReanimatedDrawerExample ref={ref}>
@@ -5,6 +5,8 @@ import { IMessageItem, SessionDetailResponse } from '../../types/dto';
5
5
  import { DeviceEventEmitter } from 'react-native';
6
6
  import { events } from '../../constants/events';
7
7
  import useStreamMessageStore from '../../store/streamMessage';
8
+ import { useQueryClient } from '@tanstack/react-query';
9
+ import { QUERY_KEYS } from '../../constants/query';
8
10
 
9
11
  const initialState = {
10
12
  id: '',
@@ -18,6 +20,7 @@ const initialState = {
18
20
  messages: [],
19
21
  };
20
22
  export const useMessage = () => {
23
+ const queryClient = useQueryClient();
21
24
  const sessionId = useSessionStore((state) => state.sessionId);
22
25
  const { mutateAsync: getSessionById } = useFetchSessionById();
23
26
  const [loadState, setLoadState] =
@@ -111,6 +114,9 @@ export const useMessage = () => {
111
114
  useStreamMessageStore
112
115
  .getState()
113
116
  .clearStreamMessageRecordById(messages.map((m) => m.id));
117
+ queryClient.refetchQueries({
118
+ queryKey: [QUERY_KEYS.GET_EXTERNAL_SESSION_INFO],
119
+ });
114
120
  }
115
121
  );
116
122
  const subUpdateMessageError = DeviceEventEmitter.addListener(
@@ -152,7 +158,7 @@ export const useMessage = () => {
152
158
  subForceUpdateMessages.remove();
153
159
  subUpdateMessageError.remove();
154
160
  };
155
- }, []);
161
+ }, [queryClient]);
156
162
 
157
163
  return {
158
164
  messageState: loadState,
@@ -23,6 +23,7 @@ export const useSendMessage = () => {
23
23
  const { mutateAsync: createSession } = useCreateSession();
24
24
  const queryClient = useQueryClient();
25
25
  const logGA = useChatContext().logGA;
26
+ const setTabIndex = useChatContext().setTabIndex;
26
27
 
27
28
  const onSendMessage = useCallback(
28
29
  async (
@@ -30,6 +31,7 @@ export const useSendMessage = () => {
30
31
  attachments?: IAttachment[],
31
32
  actionType?: SendActionLogType
32
33
  ) => {
34
+ setTabIndex(0);
33
35
  const messageId = dayjs().valueOf().toString();
34
36
  const messageItem: IMessageItem = {
35
37
  id: messageId,
@@ -112,7 +114,7 @@ export const useSendMessage = () => {
112
114
  messageId
113
115
  );
114
116
  },
115
- [startStream, createSession, queryClient, logGA]
117
+ [startStream, createSession, queryClient, logGA, setTabIndex]
116
118
  );
117
119
 
118
120
  return {