@envive-ai/react-toolkit-v3 0.3.6 → 0.3.7
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/dist/AnimatedText/AnimatedText.d.cts +3 -3
- package/dist/AnimatedText/AnimatedText.d.ts +3 -3
- package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.cts +2 -2
- package/dist/CSSVariablesEditor/CssVariablesEditorComponent.d.ts +2 -2
- package/dist/Carousel/Carousel.d.cts +2 -2
- package/dist/Carousel/Carousel.d.ts +2 -2
- package/dist/ChatFooter/ChatFooter.d.cts +2 -2
- package/dist/ChatFooter/ChatFooter.d.ts +2 -2
- package/dist/ChatFooter/components/index.d.cts +5 -5
- package/dist/ChatFooter/components/index.d.ts +5 -5
- package/dist/ChatFooter/hooks/useGetContainerProperties.cjs +2 -2
- package/dist/ChatFooter/hooks/useGetContainerProperties.js +2 -2
- package/dist/ChatHeader/ChatHeader.cjs +3 -2
- package/dist/ChatHeader/ChatHeader.d.cts +3 -2
- package/dist/ChatHeader/ChatHeader.d.ts +3 -2
- package/dist/ChatHeader/ChatHeader.js +3 -2
- package/dist/ChatHeader/components/Handle.cjs +27 -1
- package/dist/ChatHeader/components/Handle.js +27 -1
- package/dist/ChatHeader/types/index.d.cts +2 -0
- package/dist/ChatHeader/types/index.d.ts +2 -0
- package/dist/ChatPreview/ChatPreview.d.cts +2 -2
- package/dist/ChatPreview/ChatPreview.d.ts +2 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.d.cts +2 -2
- package/dist/ChatPreviewComparison/ChatPreviewComparison.d.ts +2 -2
- package/dist/ChatPreviewLoading/ChatPreviewLoading.d.cts +2 -2
- package/dist/ChatPreviewLoading/ChatPreviewLoading.d.ts +2 -2
- package/dist/Container/Container.d.cts +176 -176
- package/dist/Container/Container.d.ts +176 -176
- package/dist/DesignTokens/DesignTokensComponent.d.cts +2 -2
- package/dist/DesignTokens/DesignTokensComponent.d.ts +2 -2
- package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.cts +2 -2
- package/dist/DocumentRetrievalCard/DocumentRetrievalCard.d.ts +2 -2
- package/dist/FloatingButton/FloatingButton.cjs +2 -1
- package/dist/FloatingButton/FloatingButton.d.cts +4 -3
- package/dist/FloatingButton/FloatingButton.d.ts +4 -3
- package/dist/FloatingButton/FloatingButton.js +2 -1
- package/dist/FloatingButton/components/Container.cjs +2 -2
- package/dist/FloatingButton/components/Container.js +2 -2
- package/dist/FloatingButton/hooks/useGetContainerProperties.cjs +2 -2
- package/dist/FloatingButton/hooks/useGetContainerProperties.js +2 -2
- package/dist/FloatingButton/types/types.cjs +4 -4
- package/dist/FloatingButton/types/types.d.cts +8 -4
- package/dist/FloatingButton/types/types.d.ts +8 -4
- package/dist/FloatingButton/types/types.js +4 -4
- package/dist/FloatingChat/FloatingChat.cjs +106 -39
- package/dist/FloatingChat/FloatingChat.d.cts +3 -2
- package/dist/FloatingChat/FloatingChat.d.ts +3 -2
- package/dist/FloatingChat/FloatingChat.js +108 -41
- package/dist/FloatingChat/components/AgentMessage.cjs +3 -2
- package/dist/FloatingChat/components/AgentMessage.js +3 -2
- package/dist/FloatingChat/components/ChatMessages.cjs +59 -41
- package/dist/FloatingChat/components/ChatMessages.js +58 -40
- package/dist/FloatingChat/components/Layout.cjs +2 -2
- package/dist/FloatingChat/components/Layout.js +2 -2
- package/dist/FloatingChat/components/ModalSheet.cjs +184 -0
- package/dist/FloatingChat/components/ModalSheet.js +182 -0
- package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.cjs +3 -2
- package/dist/FloatingChat/components/SalesAgentProductCardsCarousel.js +3 -2
- package/dist/FloatingChat/components/index.cjs +1 -0
- package/dist/FloatingChat/components/index.js +1 -0
- package/dist/FloatingChat/hooks/useChatSuggestions.cjs +25 -0
- package/dist/FloatingChat/hooks/useChatSuggestions.js +24 -0
- package/dist/FloatingChat/hooks/useFilteredChatMessages.cjs +24 -0
- package/dist/FloatingChat/hooks/useFilteredChatMessages.js +23 -0
- package/dist/FloatingChat/hooks/usePreventScroll.cjs +117 -0
- package/dist/FloatingChat/hooks/usePreventScroll.js +116 -0
- package/dist/FloatingChat/hooks/useSnapCalculator.cjs +37 -0
- package/dist/FloatingChat/hooks/useSnapCalculator.js +35 -0
- package/dist/FloatingChat/hooks/useSnapControl.cjs +82 -0
- package/dist/FloatingChat/hooks/useSnapControl.js +81 -0
- package/dist/FloatingChat/hooks/useSnapSetup.cjs +59 -0
- package/dist/FloatingChat/hooks/useSnapSetup.js +58 -0
- package/dist/FloatingChat/types/types.d.cts +4 -0
- package/dist/FloatingChat/types/types.d.ts +4 -0
- package/dist/Image/Image.d.cts +2 -2
- package/dist/Image/Image.d.ts +2 -2
- package/dist/ImageGallery/ImageGallery.d.cts +2 -2
- package/dist/ImageGallery/ImageGallery.d.ts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.d.cts +2 -2
- package/dist/MarkdownProcessor/MarkdownProcessor.d.ts +2 -2
- package/dist/PromptButton/PromptButton.d.cts +2 -2
- package/dist/PromptButton/PromptButton.d.ts +2 -2
- package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.cts +2 -2
- package/dist/PromptButtonCarouselWithImage/PromptButtonCarouselWithImage.d.ts +2 -2
- package/dist/PromptCarousel/PromptCarousel.cjs +0 -1
- package/dist/PromptCarousel/PromptCarousel.d.cts +2 -2
- package/dist/PromptCarousel/PromptCarousel.d.ts +2 -2
- package/dist/PromptCarousel/PromptCarousel.js +0 -1
- package/dist/ReviewCard/ReviewCard.d.cts +2 -2
- package/dist/ReviewCard/ReviewCard.d.ts +2 -2
- package/dist/ReviewCard/components/index.d.cts +6 -6
- package/dist/ReviewCard/components/index.d.ts +6 -6
- package/dist/SalesAgentProductCard/SalesAgentProductCard.d.cts +2 -2
- package/dist/SalesAgentProductCard/SalesAgentProductCard.d.ts +2 -2
- package/dist/SalesAgentProductCard/components/index.d.cts +2 -2
- package/dist/SalesAgentProductCard/components/index.d.ts +8 -8
- package/dist/SocialProof/SocialProof.cjs +9 -2
- package/dist/SocialProof/SocialProof.d.cts +2 -2
- package/dist/SocialProof/SocialProof.d.ts +2 -2
- package/dist/SocialProof/SocialProof.js +9 -2
- package/dist/SocialProof/hooks/index.cjs +1 -0
- package/dist/SocialProof/hooks/index.js +3 -0
- package/dist/SocialProof/hooks/useSocialProofCount.cjs +48 -0
- package/dist/SocialProof/hooks/useSocialProofCount.d.cts +15 -0
- package/dist/SocialProof/hooks/useSocialProofCount.d.ts +15 -0
- package/dist/SocialProof/hooks/useSocialProofCount.js +46 -0
- package/dist/SocialProof/index.cjs +5 -1
- package/dist/SocialProof/index.d.cts +3 -2
- package/dist/SocialProof/index.d.ts +3 -2
- package/dist/SocialProof/index.js +4 -2
- package/dist/SocialProof/types/types.cjs +8 -1
- package/dist/SocialProof/types/types.d.cts +16 -6
- package/dist/SocialProof/types/types.d.ts +16 -6
- package/dist/SocialProof/types/types.js +7 -1
- package/dist/Stack/Stack.d.cts +2 -2
- package/dist/TitledPromptCarousel/TitledPromptCarousel.d.cts +2 -2
- package/dist/TitledPromptCarousel/TitledPromptCarousel.d.ts +2 -2
- package/dist/TypingAnimation/TypingAnimation.d.cts +2 -2
- package/dist/TypingAnimation/TypingAnimation.d.ts +2 -2
- package/dist/Typography/Typography.d.cts +4 -4
- package/dist/Typography/Typography.d.ts +4 -4
- package/dist/WidgetTextField/WidgetTextField.d.cts +2 -2
- package/dist/WidgetTextField/WidgetTextField.d.ts +2 -2
- package/dist/WidgetWrapper/WidgetWrapper.d.cts +2 -2
- package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.cts +2 -2
- package/dist/WidgetWrapperWithTitle/WidgetWrapperWithTitle.d.ts +2 -2
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ChatFooter/hooks/useGetContainerProperties.ts +2 -2
- package/src/components/ChatHeader/ChatHeader.tsx +2 -0
- package/src/components/ChatHeader/components/Handle.tsx +29 -1
- package/src/components/ChatHeader/types/index.ts +3 -0
- package/src/components/FloatingButton/FloatingButton.tsx +2 -0
- package/src/components/FloatingButton/components/Container.tsx +3 -0
- package/src/components/FloatingButton/hooks/useGetContainerProperties.ts +2 -1
- package/src/components/FloatingButton/types/types.ts +9 -4
- package/src/components/FloatingChat/FloatingChat.tsx +160 -59
- package/src/components/FloatingChat/components/AgentMessage.tsx +3 -0
- package/src/components/FloatingChat/components/ChatMessages.tsx +25 -0
- package/src/components/FloatingChat/components/Layout.tsx +2 -2
- package/src/components/FloatingChat/components/ModalSheet.tsx +288 -0
- package/src/components/FloatingChat/components/SalesAgentProductCardsCarousel.tsx +7 -2
- package/src/components/FloatingChat/components/index.ts +3 -0
- package/src/components/FloatingChat/hooks/useChatSuggestions.ts +49 -0
- package/src/components/FloatingChat/hooks/useFilteredChatMessages.ts +43 -0
- package/src/components/FloatingChat/hooks/usePreventScroll.ts +207 -0
- package/src/components/FloatingChat/hooks/useSnapCalculator.ts +41 -0
- package/src/components/FloatingChat/hooks/useSnapControl.ts +131 -0
- package/src/components/FloatingChat/hooks/useSnapSetup.ts +106 -0
- package/src/components/FloatingChat/types/types.ts +4 -0
- package/src/components/PromptCarousel/PromptCarousel.tsx +0 -1
- package/src/components/SocialProof/SocialProof.tsx +8 -2
- package/src/components/SocialProof/__tests__/SocialProof.test.tsx +66 -17
- package/src/components/SocialProof/hooks/index.ts +2 -0
- package/src/components/SocialProof/hooks/useSocialProofCount.ts +67 -0
- package/src/components/SocialProof/index.ts +2 -1
- package/src/components/SocialProof/types/types.ts +18 -6
|
@@ -2,12 +2,15 @@ import '@testing-library/jest-dom';
|
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
4
4
|
import { SocialProof } from '../SocialProof';
|
|
5
|
-
import { DynamicLayout } from '../types/types';
|
|
5
|
+
import { DynamicLayout, PageVariant } from '../types/types';
|
|
6
6
|
import { ImageGalleryLayout } from '../../ImageGallery/types/types';
|
|
7
7
|
import { PromptButtonVariant } from '../../PromptButton/types';
|
|
8
8
|
import { PromptCarouselRows } from '../../PromptCarousel/types/types';
|
|
9
9
|
import { WidgetWrapperVariant } from '../../WidgetWrapper/types/types';
|
|
10
10
|
import { Theme } from '../../Tokens';
|
|
11
|
+
import { SOCIAL_PROOF_COUNT_KEY } from '../hooks';
|
|
12
|
+
|
|
13
|
+
const COUNT_KEY_MOCK = 'test-social-proof';
|
|
11
14
|
|
|
12
15
|
const mockUseCheckIsMobile = vi.fn(() => ({ isMobile: false, viewportWidth: 1024 }));
|
|
13
16
|
vi.mock('../../utils/useCheckIsMobile', () => ({
|
|
@@ -26,12 +29,35 @@ vi.mock('src/components/utils/useGetContentSize', () => ({
|
|
|
26
29
|
}),
|
|
27
30
|
}));
|
|
28
31
|
|
|
32
|
+
const localStorageMock = (() => {
|
|
33
|
+
let store: Record<string, string> = {};
|
|
34
|
+
return {
|
|
35
|
+
getItem: (key: string) => store[key] || null,
|
|
36
|
+
setItem: (key: string, value: string) => {
|
|
37
|
+
store[key] = value.toString();
|
|
38
|
+
},
|
|
39
|
+
removeItem: (key: string) => {
|
|
40
|
+
delete store[key];
|
|
41
|
+
},
|
|
42
|
+
clear: () => {
|
|
43
|
+
store = {};
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
|
|
48
|
+
Object.defineProperty(window, 'localStorage', {
|
|
49
|
+
value: localStorageMock,
|
|
50
|
+
});
|
|
51
|
+
|
|
29
52
|
describe('SocialProof', () => {
|
|
30
53
|
const defaultProps = {
|
|
31
|
-
baseProps: {
|
|
54
|
+
baseProps: {
|
|
55
|
+
id: 'test-social-proof',
|
|
56
|
+
pageVariant: PageVariant.PageVisit,
|
|
57
|
+
countKey: COUNT_KEY_MOCK,
|
|
58
|
+
},
|
|
32
59
|
widgetContentProps: {
|
|
33
60
|
titleLabel: 'Shopping Assistant',
|
|
34
|
-
numberOfCustomersText: '114 customers',
|
|
35
61
|
customerQueryText: 'asked which products are best for gifting...',
|
|
36
62
|
primaryButtonText: 'This is a prompt button',
|
|
37
63
|
secondaryButtonTitleText: 'What else are customers asking?',
|
|
@@ -61,14 +87,37 @@ describe('SocialProof', () => {
|
|
|
61
87
|
beforeEach(() => {
|
|
62
88
|
vi.clearAllMocks();
|
|
63
89
|
mockUseCheckIsMobile.mockReturnValue({ isMobile: false, viewportWidth: 1024 });
|
|
90
|
+
localStorageMock.clear();
|
|
64
91
|
});
|
|
65
92
|
|
|
66
93
|
describe('Basic rendering', () => {
|
|
67
|
-
it('should render with default props', () => {
|
|
94
|
+
it('should render with default props', async () => {
|
|
68
95
|
render(<SocialProof {...defaultProps} />);
|
|
69
|
-
|
|
96
|
+
// Customer count should be between 100-200 and formatted as "{number} customers"
|
|
97
|
+
const customerCountText = screen.getByText(/\d+ customers/);
|
|
98
|
+
expect(customerCountText).toBeInTheDocument();
|
|
99
|
+
const match = customerCountText.textContent?.match(/(\d+)/);
|
|
100
|
+
if (match) {
|
|
101
|
+
const count = parseInt(match[1], 10);
|
|
102
|
+
expect(count).toBeGreaterThanOrEqual(100);
|
|
103
|
+
expect(count).toBeLessThanOrEqual(200);
|
|
104
|
+
}
|
|
70
105
|
expect(screen.getByText('asked which products are best for gifting...')).toBeInTheDocument();
|
|
71
106
|
expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
|
|
107
|
+
|
|
108
|
+
// Verify persistence of customer count in localStorage:
|
|
109
|
+
await waitFor(() => {
|
|
110
|
+
const storedData = localStorageMock.getItem(SOCIAL_PROOF_COUNT_KEY);
|
|
111
|
+
expect(storedData).not.toBeNull();
|
|
112
|
+
if (storedData) {
|
|
113
|
+
const customerCountMap = JSON.parse(storedData);
|
|
114
|
+
expect(customerCountMap).toHaveProperty(PageVariant.PageVisit);
|
|
115
|
+
expect(customerCountMap[PageVariant.PageVisit]).toHaveProperty(COUNT_KEY_MOCK);
|
|
116
|
+
const storedCount = customerCountMap[PageVariant.PageVisit][COUNT_KEY_MOCK];
|
|
117
|
+
expect(storedCount).toBeGreaterThanOrEqual(100);
|
|
118
|
+
expect(storedCount).toBeLessThanOrEqual(200);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
72
121
|
});
|
|
73
122
|
|
|
74
123
|
it('should apply id attribute when provided', () => {
|
|
@@ -124,7 +173,7 @@ describe('SocialProof', () => {
|
|
|
124
173
|
widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
|
|
125
174
|
/>,
|
|
126
175
|
);
|
|
127
|
-
expect(screen.getByText(
|
|
176
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
128
177
|
expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
|
|
129
178
|
});
|
|
130
179
|
|
|
@@ -135,7 +184,7 @@ describe('SocialProof', () => {
|
|
|
135
184
|
widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.FOUR_HORIZONTAL }}
|
|
136
185
|
/>,
|
|
137
186
|
);
|
|
138
|
-
expect(screen.getByText(
|
|
187
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
139
188
|
expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
|
|
140
189
|
});
|
|
141
190
|
|
|
@@ -146,7 +195,7 @@ describe('SocialProof', () => {
|
|
|
146
195
|
widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.SINGLE }}
|
|
147
196
|
/>,
|
|
148
197
|
);
|
|
149
|
-
expect(screen.getByText(
|
|
198
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
150
199
|
expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
|
|
151
200
|
});
|
|
152
201
|
|
|
@@ -158,7 +207,7 @@ describe('SocialProof', () => {
|
|
|
158
207
|
widgetStyleProps={{ imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
|
|
159
208
|
/>,
|
|
160
209
|
);
|
|
161
|
-
expect(screen.getByText(
|
|
210
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
162
211
|
expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
|
|
163
212
|
});
|
|
164
213
|
|
|
@@ -172,7 +221,7 @@ describe('SocialProof', () => {
|
|
|
172
221
|
}}
|
|
173
222
|
/>,
|
|
174
223
|
);
|
|
175
|
-
expect(screen.getByText(
|
|
224
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
176
225
|
expect(screen.getByText('This is a prompt button')).toBeInTheDocument();
|
|
177
226
|
});
|
|
178
227
|
});
|
|
@@ -199,7 +248,7 @@ describe('SocialProof', () => {
|
|
|
199
248
|
widgetStyleProps={{ hideImage: false, imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
|
|
200
249
|
/>,
|
|
201
250
|
);
|
|
202
|
-
expect(screen.getByText(
|
|
251
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
203
252
|
});
|
|
204
253
|
|
|
205
254
|
it('should hide textfield when hideTextField is true', () => {
|
|
@@ -311,7 +360,7 @@ describe('SocialProof', () => {
|
|
|
311
360
|
widgetStyleProps={{ theme, imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
|
|
312
361
|
/>,
|
|
313
362
|
);
|
|
314
|
-
expect(screen.getByText(
|
|
363
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
315
364
|
unmount();
|
|
316
365
|
});
|
|
317
366
|
});
|
|
@@ -331,7 +380,7 @@ describe('SocialProof', () => {
|
|
|
331
380
|
widgetStyleProps={{ variant, imageGalleryLayout: ImageGalleryLayout.FOUR_GRID }}
|
|
332
381
|
/>,
|
|
333
382
|
);
|
|
334
|
-
expect(screen.getByText(
|
|
383
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
335
384
|
unmount();
|
|
336
385
|
});
|
|
337
386
|
});
|
|
@@ -416,7 +465,7 @@ describe('SocialProof', () => {
|
|
|
416
465
|
}}
|
|
417
466
|
/>,
|
|
418
467
|
);
|
|
419
|
-
expect(screen.getByText(
|
|
468
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
420
469
|
});
|
|
421
470
|
|
|
422
471
|
it('should render with dynamicLayout WIDE', () => {
|
|
@@ -429,7 +478,7 @@ describe('SocialProof', () => {
|
|
|
429
478
|
}}
|
|
430
479
|
/>,
|
|
431
480
|
);
|
|
432
|
-
expect(screen.getByText(
|
|
481
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
433
482
|
});
|
|
434
483
|
});
|
|
435
484
|
|
|
@@ -450,7 +499,7 @@ describe('SocialProof', () => {
|
|
|
450
499
|
widgetEventProps={{ handleTextFieldClick: vi.fn() }}
|
|
451
500
|
/>,
|
|
452
501
|
);
|
|
453
|
-
expect(screen.getByText(
|
|
502
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
454
503
|
});
|
|
455
504
|
|
|
456
505
|
it('should render with empty secondaryButtonTexts array', () => {
|
|
@@ -463,7 +512,7 @@ describe('SocialProof', () => {
|
|
|
463
512
|
}}
|
|
464
513
|
/>,
|
|
465
514
|
);
|
|
466
|
-
expect(screen.getByText(
|
|
515
|
+
expect(screen.getByText(/\d+ customers/)).toBeInTheDocument();
|
|
467
516
|
});
|
|
468
517
|
});
|
|
469
518
|
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { PageVariant } from '../types/types';
|
|
3
|
+
|
|
4
|
+
const RANDOM_NUMBER_MIN = 100;
|
|
5
|
+
const RANDOM_NUMBER_MAX = 200;
|
|
6
|
+
export const SOCIAL_PROOF_COUNT_KEY = 'v3_social_proof_values';
|
|
7
|
+
|
|
8
|
+
type SocialProofCount = Record<string, Record<string, number>>;
|
|
9
|
+
|
|
10
|
+
interface UseSocialProofCountParams {
|
|
11
|
+
pageVariant?: PageVariant;
|
|
12
|
+
countKey?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const useSocialProofCount = ({
|
|
17
|
+
pageVariant,
|
|
18
|
+
countKey,
|
|
19
|
+
id,
|
|
20
|
+
}: UseSocialProofCountParams): string => {
|
|
21
|
+
const [customerCount, setCustomerCount] = useState<number>(() =>
|
|
22
|
+
Math.floor(Math.random() * (RANDOM_NUMBER_MAX - RANDOM_NUMBER_MIN + 1) + RANDOM_NUMBER_MIN),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const variant = pageVariant || PageVariant.PageVisit;
|
|
27
|
+
const key = countKey || id || 'default';
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const storedData = localStorage.getItem(SOCIAL_PROOF_COUNT_KEY);
|
|
31
|
+
let customerCountMap: SocialProofCount = {};
|
|
32
|
+
|
|
33
|
+
if (storedData) {
|
|
34
|
+
try {
|
|
35
|
+
customerCountMap = JSON.parse(storedData) as SocialProofCount;
|
|
36
|
+
} catch (parseError) {
|
|
37
|
+
console.warn('Failed to parse social proof count from localStorage:', parseError);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (customerCountMap[variant]?.[key]) {
|
|
43
|
+
setCustomerCount(customerCountMap[variant][key]);
|
|
44
|
+
} else {
|
|
45
|
+
const randomCount = Math.floor(
|
|
46
|
+
Math.random() * (RANDOM_NUMBER_MAX - RANDOM_NUMBER_MIN + 1) + RANDOM_NUMBER_MIN,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (!customerCountMap[variant]) {
|
|
50
|
+
customerCountMap[variant] = {};
|
|
51
|
+
}
|
|
52
|
+
customerCountMap[variant][key] = randomCount;
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
localStorage.setItem(SOCIAL_PROOF_COUNT_KEY, JSON.stringify(customerCountMap));
|
|
56
|
+
setCustomerCount(randomCount);
|
|
57
|
+
} catch (storageError) {
|
|
58
|
+
console.warn('Failed to save social proof count to localStorage:', storageError);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.warn('Error managing social proof count:', error);
|
|
63
|
+
}
|
|
64
|
+
}, [pageVariant, countKey, id]);
|
|
65
|
+
|
|
66
|
+
return `${customerCount} customers`;
|
|
67
|
+
};
|
|
@@ -9,6 +9,12 @@ export enum DynamicLayout {
|
|
|
9
9
|
WIDE = 'wide',
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
export enum PageVariant {
|
|
13
|
+
PLP = 'PLP',
|
|
14
|
+
PDP = 'PDP',
|
|
15
|
+
PageVisit = 'PageVisit',
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
/**
|
|
13
19
|
* Base props for the SocialProof component container.
|
|
14
20
|
*
|
|
@@ -34,6 +40,18 @@ export type BaseProps = {
|
|
|
34
40
|
* Inline styles to apply to the container.
|
|
35
41
|
*/
|
|
36
42
|
style?: React.CSSProperties;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Page variant for localStorage persistence of customer counts (PLP, PDP, or PageVisit).
|
|
46
|
+
*/
|
|
47
|
+
pageVariant?: PageVariant;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Specific identifier for the pageVariant (e.g., productId for PDP, plpId for PLP, category for PageVisit).
|
|
51
|
+
* Used as the key for localStorage persistence.
|
|
52
|
+
* Falls back to the `id` prop if not provided.
|
|
53
|
+
*/
|
|
54
|
+
countKey?: string;
|
|
37
55
|
};
|
|
38
56
|
|
|
39
57
|
/**
|
|
@@ -53,12 +71,6 @@ export type WidgetContentProps = {
|
|
|
53
71
|
*/
|
|
54
72
|
titleLabel: string;
|
|
55
73
|
|
|
56
|
-
/**
|
|
57
|
-
* Text displaying the number of customers (e.g., "114 customers").
|
|
58
|
-
* Displayed in the headline section.
|
|
59
|
-
*/
|
|
60
|
-
numberOfCustomersText?: string;
|
|
61
|
-
|
|
62
74
|
/**
|
|
63
75
|
* Text displaying what customers asked (e.g., "asked which products are best for gifting...").
|
|
64
76
|
* Displayed in the headline section alongside the customer count.
|