@solucx/react-native-solucx-widget 0.2.5 → 2.0.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/README.md +526 -182
- package/lib/SoluCXWidget.d.ts +50 -7
- package/lib/SoluCXWidget.d.ts.map +1 -1
- package/lib/SoluCXWidget.js +105 -101
- package/lib/SoluCXWidget.js.map +1 -1
- package/lib/SoluCXWidgetHost.d.ts +3 -0
- package/lib/SoluCXWidgetHost.d.ts.map +1 -0
- package/lib/SoluCXWidgetHost.js +34 -0
- package/lib/SoluCXWidgetHost.js.map +1 -0
- package/lib/SoluCXWidgetView.d.ts +12 -0
- package/lib/SoluCXWidgetView.d.ts.map +1 -0
- package/lib/SoluCXWidgetView.js +61 -0
- package/lib/SoluCXWidgetView.js.map +1 -0
- package/lib/components/CloseButton.d.ts +1 -1
- package/lib/components/CloseButton.d.ts.map +1 -1
- package/lib/components/CloseButton.js +4 -1
- package/lib/components/CloseButton.js.map +1 -1
- package/lib/components/InlineWidget.d.ts.map +1 -1
- package/lib/components/InlineWidget.js +2 -7
- package/lib/components/InlineWidget.js.map +1 -1
- package/lib/components/ModalWidget.d.ts +1 -1
- package/lib/components/ModalWidget.d.ts.map +1 -1
- package/lib/components/ModalWidget.js +3 -16
- package/lib/components/ModalWidget.js.map +1 -1
- package/lib/components/OverlayWidget.d.ts.map +1 -1
- package/lib/components/OverlayWidget.js +5 -15
- package/lib/components/OverlayWidget.js.map +1 -1
- package/lib/components/index.d.ts +5 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +12 -0
- package/lib/components/index.js.map +1 -0
- package/lib/constants/Constants.d.ts +11 -0
- package/lib/constants/Constants.d.ts.map +1 -1
- package/lib/constants/Constants.js +16 -1
- package/lib/constants/Constants.js.map +1 -1
- package/lib/{interfaces → domain}/WidgetCallbacks.d.ts +2 -2
- package/lib/domain/WidgetCallbacks.d.ts.map +1 -0
- package/lib/domain/WidgetCallbacks.js.map +1 -0
- package/{src/interfaces/WidgetData.ts → lib/domain/WidgetData.d.ts} +5 -2
- package/lib/domain/WidgetData.d.ts.map +1 -0
- package/lib/{interfaces → domain}/WidgetData.js.map +1 -1
- package/lib/domain/WidgetDisplayResult.d.ts +6 -0
- package/lib/domain/WidgetDisplayResult.d.ts.map +1 -0
- package/lib/domain/WidgetDisplayResult.js +3 -0
- package/lib/domain/WidgetDisplayResult.js.map +1 -0
- package/lib/domain/WidgetOptions.d.ts +27 -0
- package/lib/domain/WidgetOptions.d.ts.map +1 -0
- package/lib/domain/WidgetOptions.js +30 -0
- package/lib/domain/WidgetOptions.js.map +1 -0
- package/lib/domain/WidgetResponse.d.ts +5 -0
- package/lib/domain/WidgetResponse.d.ts.map +1 -0
- package/lib/{interfaces/WidgetOptions.js → domain/WidgetResponse.js} +1 -1
- package/lib/domain/WidgetResponse.js.map +1 -0
- package/lib/domain/WidgetSamplerLog.d.ts +12 -0
- package/lib/domain/WidgetSamplerLog.d.ts.map +1 -0
- package/lib/domain/WidgetSamplerLog.js.map +1 -0
- package/lib/{interfaces → domain}/index.d.ts +1 -2
- package/lib/domain/index.d.ts.map +1 -0
- package/lib/{interfaces → domain}/index.js.map +1 -1
- package/lib/hooks/index.d.ts +2 -2
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/index.js +5 -5
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/useClientVersionCollector.d.ts +3 -0
- package/lib/hooks/useClientVersionCollector.d.ts.map +1 -0
- package/lib/{services/ClientVersionCollector.js → hooks/useClientVersionCollector.js} +7 -2
- package/lib/hooks/useClientVersionCollector.js.map +1 -0
- package/lib/hooks/useHeightAnimation.d.ts +0 -1
- package/lib/hooks/useHeightAnimation.d.ts.map +1 -1
- package/lib/hooks/useHeightAnimation.js +4 -2
- package/lib/hooks/useHeightAnimation.js.map +1 -1
- package/lib/hooks/useWidget.d.ts +13 -0
- package/lib/hooks/useWidget.d.ts.map +1 -0
- package/lib/hooks/useWidget.js +44 -0
- package/lib/hooks/useWidget.js.map +1 -0
- package/lib/hooks/useWidgetBootstrap.d.ts +21 -0
- package/lib/hooks/useWidgetBootstrap.d.ts.map +1 -0
- package/lib/hooks/useWidgetBootstrap.js +87 -0
- package/lib/hooks/useWidgetBootstrap.js.map +1 -0
- package/lib/hooks/useWidgetServices.d.ts +19 -0
- package/lib/hooks/useWidgetServices.d.ts.map +1 -0
- package/lib/hooks/useWidgetServices.js +34 -0
- package/lib/hooks/useWidgetServices.js.map +1 -0
- package/lib/hooks/useWidgetUI.d.ts +9 -0
- package/lib/hooks/useWidgetUI.d.ts.map +1 -0
- package/lib/hooks/useWidgetUI.js +33 -0
- package/lib/hooks/useWidgetUI.js.map +1 -0
- package/lib/index.d.ts +10 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -38
- package/lib/index.js.map +1 -1
- package/lib/services/UserIdentificationService.d.ts +3 -0
- package/lib/services/UserIdentificationService.d.ts.map +1 -0
- package/lib/services/UserIdentificationService.js +17 -0
- package/lib/services/UserIdentificationService.js.map +1 -0
- package/lib/services/WidgetBootstrapService.d.ts +12 -0
- package/lib/services/WidgetBootstrapService.d.ts.map +1 -0
- package/lib/services/{widgetBootstrapService.js → WidgetBootstrapService.js} +36 -15
- package/lib/services/WidgetBootstrapService.js.map +1 -0
- package/lib/services/WidgetEventService.d.ts +8 -0
- package/lib/services/WidgetEventService.d.ts.map +1 -0
- package/lib/services/WidgetEventService.js +14 -0
- package/lib/services/WidgetEventService.js.map +1 -0
- package/lib/services/WidgetStateManager.d.ts +20 -0
- package/lib/services/WidgetStateManager.d.ts.map +1 -0
- package/lib/services/WidgetStateManager.js +93 -0
- package/lib/services/WidgetStateManager.js.map +1 -0
- package/lib/services/WidgetValidationService.d.ts +17 -0
- package/lib/services/WidgetValidationService.d.ts.map +1 -0
- package/lib/services/WidgetValidationService.js +132 -0
- package/lib/services/WidgetValidationService.js.map +1 -0
- package/lib/services/events/EventHandlerFactory.d.ts +18 -0
- package/lib/services/events/EventHandlerFactory.d.ts.map +1 -0
- package/lib/services/events/EventHandlerFactory.js +67 -0
- package/lib/services/events/EventHandlerFactory.js.map +1 -0
- package/lib/services/events/EventHandlers.d.ts +10 -0
- package/lib/services/events/EventHandlers.d.ts.map +1 -0
- package/lib/services/events/EventHandlers.js +72 -0
- package/lib/services/events/EventHandlers.js.map +1 -0
- package/lib/services/events/index.d.ts +3 -0
- package/lib/services/events/index.d.ts.map +1 -0
- package/lib/services/events/index.js +21 -0
- package/lib/services/events/index.js.map +1 -0
- package/lib/services/height/HeightStrategies.d.ts +3 -0
- package/lib/services/height/HeightStrategies.d.ts.map +1 -0
- package/lib/services/height/HeightStrategies.js +14 -0
- package/lib/services/height/HeightStrategies.js.map +1 -0
- package/lib/services/storage/AsyncStorageService.d.ts +13 -0
- package/lib/services/storage/AsyncStorageService.d.ts.map +1 -0
- package/lib/services/storage/AsyncStorageService.js +73 -0
- package/lib/services/storage/AsyncStorageService.js.map +1 -0
- package/lib/services/storage/IStorageService.d.ts +30 -0
- package/lib/services/storage/IStorageService.d.ts.map +1 -0
- package/lib/services/storage/IStorageService.js +3 -0
- package/lib/services/storage/IStorageService.js.map +1 -0
- package/lib/services/storage/StorageIdBuilder.d.ts +11 -0
- package/lib/services/storage/StorageIdBuilder.d.ts.map +1 -0
- package/lib/services/storage/StorageIdBuilder.js +17 -0
- package/lib/services/storage/StorageIdBuilder.js.map +1 -0
- package/lib/services/storage/index.d.ts +3 -0
- package/lib/services/storage/index.d.ts.map +1 -0
- package/lib/services/storage/index.js +6 -0
- package/lib/services/storage/index.js.map +1 -0
- package/lib/styles/widgetStyles.d.ts +1 -1
- package/lib/styles/widgetStyles.d.ts.map +1 -1
- package/package.json +8 -2
- package/src/SoluCXWidget.ts +144 -0
- package/src/SoluCXWidgetHost.tsx +44 -0
- package/src/SoluCXWidgetView.tsx +97 -0
- package/src/__tests__/ClientVersionCollector.test.ts +5 -5
- package/src/__tests__/OverlayWidget.rendering.test.tsx +12 -14
- package/src/__tests__/SoluCXWidget.rendering.test.tsx +103 -60
- package/src/__tests__/SoluCXWidget.test.ts +448 -0
- package/src/__tests__/WidgetValidationService.test.ts +408 -0
- package/src/__tests__/e2e/widget-lifecycle.test.tsx +14 -23
- package/src/__tests__/index.test.tsx +39 -0
- package/src/__tests__/integration/webview-communication-simple.test.tsx +8 -6
- package/src/__tests__/integration/webview-communication.test.tsx +127 -130
- package/src/__tests__/normalizeWidgetOptions.test.ts +80 -0
- package/src/__tests__/useWidgetBootstrap.test.ts +634 -0
- package/src/__tests__/useWidgetState.test.ts +56 -13
- package/src/__tests__/widgetBootstrapService.test.ts +15 -17
- package/src/components/CloseButton.tsx +6 -2
- package/src/components/InlineWidget.tsx +4 -9
- package/src/components/ModalWidget.tsx +15 -45
- package/src/components/OverlayWidget.tsx +5 -15
- package/src/components/index.ts +4 -0
- package/src/constants/Constants.ts +15 -0
- package/src/{interfaces → domain}/WidgetCallbacks.ts +2 -2
- package/{lib/interfaces/WidgetData.d.ts → src/domain/WidgetData.ts} +3 -2
- package/src/domain/WidgetDisplayResult.ts +16 -0
- package/src/domain/WidgetOptions.ts +53 -0
- package/src/domain/WidgetResponse.ts +5 -0
- package/src/domain/WidgetSamplerLog.ts +11 -0
- package/src/{interfaces → domain}/index.ts +1 -2
- package/src/hooks/index.ts +2 -2
- package/src/{services/ClientVersionCollector.ts → hooks/useClientVersionCollector.ts} +6 -0
- package/src/hooks/useHeightAnimation.ts +6 -3
- package/src/hooks/useWidget.ts +46 -0
- package/src/hooks/useWidgetBootstrap.ts +117 -0
- package/src/hooks/useWidgetServices.ts +44 -0
- package/src/hooks/useWidgetUI.ts +38 -0
- package/src/index.ts +16 -11
- package/src/services/UserIdentificationService.ts +14 -0
- package/src/services/{widgetBootstrapService.ts → WidgetBootstrapService.ts} +43 -19
- package/src/services/WidgetEventService.ts +15 -0
- package/src/services/WidgetStateManager.ts +115 -0
- package/src/services/WidgetValidationService.ts +149 -0
- package/src/services/events/EventHandlerFactory.ts +70 -0
- package/src/services/events/EventHandlers.ts +67 -0
- package/src/services/events/index.ts +2 -0
- package/src/services/height/HeightStrategies.ts +15 -0
- package/src/services/storage/AsyncStorageService.ts +74 -0
- package/src/services/storage/IStorageService.ts +32 -0
- package/src/services/storage/StorageIdBuilder.ts +15 -0
- package/src/services/storage/index.ts +2 -0
- package/src/styles/widgetStyles.ts +1 -1
- package/README.intern.md +0 -490
- package/lib/constants/webViewConstants.d.ts +0 -12
- package/lib/constants/webViewConstants.d.ts.map +0 -1
- package/lib/constants/webViewConstants.js +0 -19
- package/lib/constants/webViewConstants.js.map +0 -1
- package/lib/hooks/useWidgetHeight.d.ts +0 -13
- package/lib/hooks/useWidgetHeight.d.ts.map +0 -1
- package/lib/hooks/useWidgetHeight.js +0 -21
- package/lib/hooks/useWidgetHeight.js.map +0 -1
- package/lib/hooks/useWidgetState.d.ts +0 -15
- package/lib/hooks/useWidgetState.d.ts.map +0 -1
- package/lib/hooks/useWidgetState.js +0 -79
- package/lib/hooks/useWidgetState.js.map +0 -1
- package/lib/interfaces/WidgetCallbacks.d.ts.map +0 -1
- package/lib/interfaces/WidgetCallbacks.js.map +0 -1
- package/lib/interfaces/WidgetData.d.ts.map +0 -1
- package/lib/interfaces/WidgetOptions.d.ts +0 -9
- package/lib/interfaces/WidgetOptions.d.ts.map +0 -1
- package/lib/interfaces/WidgetOptions.js.map +0 -1
- package/lib/interfaces/WidgetResponse.d.ts +0 -10
- package/lib/interfaces/WidgetResponse.d.ts.map +0 -1
- package/lib/interfaces/WidgetResponse.js +0 -12
- package/lib/interfaces/WidgetResponse.js.map +0 -1
- package/lib/interfaces/WidgetSamplerLog.d.ts +0 -7
- package/lib/interfaces/WidgetSamplerLog.d.ts.map +0 -1
- package/lib/interfaces/WidgetSamplerLog.js.map +0 -1
- package/lib/interfaces/index.d.ts.map +0 -1
- package/lib/services/ClientVersionCollector.d.ts +0 -2
- package/lib/services/ClientVersionCollector.d.ts.map +0 -1
- package/lib/services/ClientVersionCollector.js.map +0 -1
- package/lib/services/storage.d.ts +0 -8
- package/lib/services/storage.d.ts.map +0 -1
- package/lib/services/storage.js +0 -23
- package/lib/services/storage.js.map +0 -1
- package/lib/services/widgetBootstrapService.d.ts +0 -6
- package/lib/services/widgetBootstrapService.d.ts.map +0 -1
- package/lib/services/widgetBootstrapService.js.map +0 -1
- package/lib/services/widgetEventService.d.ts +0 -19
- package/lib/services/widgetEventService.d.ts.map +0 -1
- package/lib/services/widgetEventService.js +0 -79
- package/lib/services/widgetEventService.js.map +0 -1
- package/lib/services/widgetValidationService.d.ts +0 -18
- package/lib/services/widgetValidationService.d.ts.map +0 -1
- package/lib/services/widgetValidationService.js +0 -71
- package/lib/services/widgetValidationService.js.map +0 -1
- package/src/SoluCXWidget.tsx +0 -179
- package/src/constants/webViewConstants.ts +0 -15
- package/src/hooks/useWidgetHeight.ts +0 -38
- package/src/hooks/useWidgetState.ts +0 -101
- package/src/interfaces/WidgetOptions.ts +0 -8
- package/src/interfaces/WidgetResponse.ts +0 -15
- package/src/interfaces/WidgetSamplerLog.ts +0 -6
- package/src/services/storage.ts +0 -21
- package/src/services/widgetEventService.ts +0 -110
- package/src/services/widgetValidationService.ts +0 -102
- /package/lib/{interfaces → domain}/WidgetCallbacks.js +0 -0
- /package/lib/{interfaces → domain}/WidgetData.js +0 -0
- /package/lib/{interfaces → domain}/WidgetSamplerLog.js +0 -0
- /package/lib/{interfaces → domain}/index.js +0 -0
package/README.md
CHANGED
|
@@ -1,285 +1,629 @@
|
|
|
1
1
|
# @solucx/react-native-solucx-widget
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/js/@solucx%2Freact-native-solucx-widget)
|
|
4
3
|
[](https://reactnative.dev/)
|
|
5
4
|
[](https://expo.dev/)
|
|
6
5
|
[](https://www.typescriptlang.org/)
|
|
7
|
-
[](https://developer.apple.com/ios/)
|
|
8
|
-
[](https://developer.android.com/)
|
|
9
|
-
[](LICENSE)
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
Widget React Native para coleta de feedback e pesquisas de satisfacao, desenvolvido pela SoluCX.
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
---
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-

|
|
17
|
-

|
|
18
|
-

|
|
19
|
-

|
|
11
|
+
## Instalacao
|
|
20
12
|
|
|
21
|
-
|
|
13
|
+
```bash
|
|
14
|
+
npm install @solucx/react-native-solucx-widget
|
|
15
|
+
```
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
---
|
|
24
18
|
|
|
25
|
-
|
|
19
|
+
## Inicio Rapido
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
- **Persistência Automática**: Controle inteligente de frequência
|
|
29
|
-
- **Comunicação WebView**: Integração transparente com plataforma SoluCX
|
|
30
|
-
- **TypeScript**: Totalmente tipado para melhor experiência de desenvolvimento
|
|
31
|
-
- **Performático**: Carregamento otimizado e cache local
|
|
21
|
+
Voce pode integrar o widget de duas formas:
|
|
32
22
|
|
|
33
|
-
|
|
23
|
+
- **Por funcao**: monta um `SoluCXWidgetHost` no root e dispara a exibicao com `SoluCXWidget.create(...).show()`.
|
|
24
|
+
- **Por componente**: renderiza `SoluCXWidget` diretamente no JSX, no ponto exato em que o widget deve aparecer.
|
|
34
25
|
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
### 1. Uso por funcao: adicione o `SoluCXWidgetHost` no root do app
|
|
27
|
+
|
|
28
|
+
O `SoluCXWidgetHost` deve ser montado **uma unica vez** no componente raiz da aplicacao. Ele e responsavel por renderizar o widget quando solicitado via `SoluCXWidget.create(...).show()`.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// App.tsx
|
|
32
|
+
import { SoluCXWidgetHost } from '@solucx/react-native-solucx-widget';
|
|
33
|
+
|
|
34
|
+
export default function App() {
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<NavigationContainer>
|
|
38
|
+
<Stack.Navigator>{/* suas telas */}</Stack.Navigator>
|
|
39
|
+
</NavigationContainer>
|
|
40
|
+
|
|
41
|
+
{/* Obrigatorio: monte uma vez no root */}
|
|
42
|
+
<SoluCXWidgetHost />
|
|
43
|
+
</>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
37
46
|
```
|
|
38
47
|
|
|
39
|
-
|
|
48
|
+
### 2. Uso por funcao: dispare o widget em qualquer tela
|
|
49
|
+
|
|
50
|
+
Use `SoluCXWidget.create()` para construir e exibir o widget. **As opcoes de supressao (dias de espera) sao opcionais** — se nao forem passadas, o widget as busca automaticamente do painel de configuracao da jornada (configurado remotamente).
|
|
40
51
|
|
|
41
52
|
```tsx
|
|
42
|
-
|
|
53
|
+
// CheckoutScreen.tsx
|
|
43
54
|
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
44
55
|
|
|
45
|
-
|
|
56
|
+
function onCheckoutComplete() {
|
|
57
|
+
SoluCXWidget
|
|
58
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
59
|
+
.setType('modal')
|
|
60
|
+
.setData({
|
|
61
|
+
journey: 'pos_venda',
|
|
62
|
+
user_id: 'user_123',
|
|
63
|
+
email: 'cliente@email.com',
|
|
64
|
+
name: 'Joao Silva',
|
|
65
|
+
})
|
|
66
|
+
.show();
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Pronto! O widget vai buscar as configuracoes de supressao remotamente e decidir se deve exibir ou nao.
|
|
71
|
+
|
|
72
|
+
### 3. Uso por componente: renderize o widget diretamente no JSX
|
|
73
|
+
|
|
74
|
+
Quando voce quiser controlar a exibicao pelo proprio componente React, use `SoluCXWidget`. Nesse modo, nao e necessario montar `SoluCXWidgetHost`.
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
// CheckoutScreen.tsx
|
|
78
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
79
|
+
|
|
80
|
+
export function CheckoutScreen() {
|
|
46
81
|
return (
|
|
47
82
|
<SoluCXWidget
|
|
48
|
-
soluCXKey=
|
|
49
|
-
type=
|
|
83
|
+
soluCXKey="SUA_CHAVE_SOLUCX"
|
|
84
|
+
type="inline"
|
|
50
85
|
data={{
|
|
51
|
-
journey: '
|
|
52
|
-
|
|
53
|
-
email: '
|
|
54
|
-
|
|
55
|
-
amount: 150.0
|
|
86
|
+
journey: 'pos_venda',
|
|
87
|
+
user_id: 'user_123',
|
|
88
|
+
email: 'cliente@email.com',
|
|
89
|
+
name: 'Joao Silva',
|
|
56
90
|
}}
|
|
57
|
-
|
|
58
|
-
|
|
91
|
+
callbacks={{
|
|
92
|
+
onOpened: (userId) => {
|
|
93
|
+
console.log('Widget exibido para:', userId);
|
|
94
|
+
},
|
|
59
95
|
}}
|
|
60
96
|
/>
|
|
61
97
|
);
|
|
62
98
|
}
|
|
63
99
|
```
|
|
64
100
|
|
|
65
|
-
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Exemplos Completos
|
|
66
104
|
|
|
67
|
-
###
|
|
105
|
+
### Exemplo 1: Uso minimo (opcoes configuradas remotamente)
|
|
68
106
|
|
|
69
|
-
|
|
107
|
+
Este e o caso de uso mais comum. As regras de supressao (quantos dias esperar apos cada evento) sao configuradas no **painel de configuracao da jornada** e buscadas automaticamente pelo widget. Voce nao precisa passar nenhuma opcao.
|
|
70
108
|
|
|
71
109
|
```tsx
|
|
72
|
-
|
|
110
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
111
|
+
|
|
112
|
+
// Disparar apos uma compra
|
|
113
|
+
function afterPurchase() {
|
|
114
|
+
SoluCXWidget
|
|
115
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
116
|
+
.setType('bottom')
|
|
117
|
+
.setData({
|
|
118
|
+
journey: 'pos_venda',
|
|
119
|
+
user_id: 'user_123',
|
|
120
|
+
email: 'cliente@email.com',
|
|
121
|
+
name: 'Joao Silva',
|
|
122
|
+
store_id: 'loja_01',
|
|
123
|
+
})
|
|
124
|
+
.show();
|
|
125
|
+
// As opcoes de supressao serao buscadas automaticamente da API
|
|
126
|
+
// com base na configuracao da jornada "pos_venda"
|
|
127
|
+
}
|
|
73
128
|
```
|
|
74
129
|
|
|
75
|
-
###
|
|
130
|
+
### Exemplo 2: Com callbacks para monitorar eventos
|
|
76
131
|
|
|
77
|
-
|
|
132
|
+
```tsx
|
|
133
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
134
|
+
|
|
135
|
+
function showSurvey() {
|
|
136
|
+
SoluCXWidget
|
|
137
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
138
|
+
.setType('modal')
|
|
139
|
+
.setData({
|
|
140
|
+
journey: 'atendimento',
|
|
141
|
+
user_id: 'user_456',
|
|
142
|
+
email: 'maria@email.com',
|
|
143
|
+
name: 'Maria Santos',
|
|
144
|
+
employee_id: 'atendente_01',
|
|
145
|
+
employee_name: 'Carlos',
|
|
146
|
+
})
|
|
147
|
+
.setCallbacks({
|
|
148
|
+
onPreOpen: (userId) => {
|
|
149
|
+
console.log('Preparando widget para:', userId);
|
|
150
|
+
},
|
|
151
|
+
onOpened: (userId) => {
|
|
152
|
+
console.log('Widget exibido para:', userId);
|
|
153
|
+
analytics.track('survey_shown', { userId });
|
|
154
|
+
},
|
|
155
|
+
onBlocked: (reason) => {
|
|
156
|
+
// Widget nao foi exibido por causa de uma regra de supressao
|
|
157
|
+
console.log('Widget bloqueado:', reason);
|
|
158
|
+
// Ex: "BLOCKED_BY_WIDGET_DISMISS_INTERVAL"
|
|
159
|
+
},
|
|
160
|
+
onClosed: () => {
|
|
161
|
+
console.log('Usuario fechou o widget');
|
|
162
|
+
},
|
|
163
|
+
onCompleted: (userId) => {
|
|
164
|
+
console.log('Pesquisa respondida por:', userId);
|
|
165
|
+
analytics.track('survey_completed', { userId });
|
|
166
|
+
},
|
|
167
|
+
onPartialCompleted: (userId) => {
|
|
168
|
+
console.log('Pesquisa parcialmente respondida por:', userId);
|
|
169
|
+
},
|
|
170
|
+
onError: (message) => {
|
|
171
|
+
console.error('Erro no widget:', message);
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
.show();
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Exemplo 3: Com opcoes locais (sobrescrevendo configuracao remota)
|
|
179
|
+
|
|
180
|
+
Se voce precisar sobrescrever as configuracoes da jornada para um caso especifico, passe as opcoes diretamente. Quando `setOptions()` e chamado, o widget **nao busca configuracoes da API** e usa os valores fornecidos.
|
|
78
181
|
|
|
79
182
|
```tsx
|
|
80
|
-
|
|
183
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
184
|
+
|
|
185
|
+
function showUrgentSurvey() {
|
|
186
|
+
SoluCXWidget
|
|
187
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
188
|
+
.setType('modal')
|
|
189
|
+
.setData({
|
|
190
|
+
journey: 'nps_trimestral',
|
|
191
|
+
user_id: 'user_789',
|
|
192
|
+
email: 'pedro@email.com',
|
|
193
|
+
})
|
|
194
|
+
.setOptions({
|
|
195
|
+
height: 600,
|
|
196
|
+
maxAttemptsAfterDismiss: 5, // Máximo de 5 tentativas para essa jornada
|
|
197
|
+
waitDaysAfterWidgetDismiss: 90, // Esperar 90 dias após o usuário fechar
|
|
198
|
+
waitDaysAfterWidgetSubmit: 30, // Esperar 30 dias após resposta completa
|
|
199
|
+
waitDaysAfterWidgetDisplay: 7, // Esperar 7 dias após qualquer exibição
|
|
200
|
+
})
|
|
201
|
+
.setCallbacks({
|
|
202
|
+
onOpened: (userId) => console.log('Abriu:', userId),
|
|
203
|
+
onCompleted: (userId) => console.log('Respondeu:', userId),
|
|
204
|
+
})
|
|
205
|
+
.show();
|
|
206
|
+
}
|
|
81
207
|
```
|
|
82
208
|
|
|
83
|
-
###
|
|
209
|
+
### Exemplo 4: Diferentes tipos de widget
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
213
|
+
|
|
214
|
+
const data = {
|
|
215
|
+
journey: 'pos_venda',
|
|
216
|
+
user_id: 'user_123',
|
|
217
|
+
email: 'cliente@email.com',
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// Bottom: barra fixa na parte inferior (padrao)
|
|
221
|
+
SoluCXWidget.create('KEY').setType('bottom').setData(data).show();
|
|
222
|
+
|
|
223
|
+
// Top: barra fixa no topo
|
|
224
|
+
SoluCXWidget.create('KEY').setType('top').setData(data).show();
|
|
225
|
+
|
|
226
|
+
// Modal: sobreposicao centralizada que bloqueia o fundo
|
|
227
|
+
SoluCXWidget.create('KEY').setType('modal').setData(data).show();
|
|
228
|
+
|
|
229
|
+
// Inline: integrado ao fluxo do layout (respeita a posicao no JSX)
|
|
230
|
+
SoluCXWidget.create('KEY').setType('inline').setData(data).show();
|
|
231
|
+
```
|
|
84
232
|
|
|
85
|
-
|
|
233
|
+
### Exemplo 5: Fechar o widget programaticamente
|
|
86
234
|
|
|
87
235
|
```tsx
|
|
88
|
-
|
|
236
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
237
|
+
|
|
238
|
+
// Fechar o widget a qualquer momento
|
|
239
|
+
function handleTimeout() {
|
|
240
|
+
SoluCXWidget.dismiss();
|
|
241
|
+
}
|
|
89
242
|
```
|
|
90
243
|
|
|
91
|
-
###
|
|
244
|
+
### Exemplo 6: Consultar logs de supressao
|
|
92
245
|
|
|
93
|
-
|
|
246
|
+
Os metodos de log sao **metodos de instancia** — usam os dados do builder (`instanceKey` do `create()`, `journey` e `userId` do `setData()`) para identificar automaticamente qual registro acessar. Nao e necessario passar esses parametros novamente.
|
|
94
247
|
|
|
95
248
|
```tsx
|
|
96
|
-
|
|
249
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
250
|
+
|
|
251
|
+
// Cria a instancia com os dados que identificam o registro
|
|
252
|
+
const widget = SoluCXWidget
|
|
253
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
254
|
+
.setData({ journey: 'pos_venda', user_id: 'user_123' });
|
|
255
|
+
|
|
256
|
+
// Consultar os logs de supressao
|
|
257
|
+
const logs = await widget.getWidgetLogs();
|
|
258
|
+
console.log(logs);
|
|
259
|
+
// {
|
|
260
|
+
// attempts: 3, // quantas vezes o widget foi exibido nesta experiencia
|
|
261
|
+
// answeredTransactionIds: ['txn-1'], // transacoes que ja responderam e nao devem reabrir o widget
|
|
262
|
+
// lastExperienceId: 'pos_venda', // ultima jornada associada ao contador
|
|
263
|
+
// lastDisplayAttempt: 1741000000000, // ultima tentativa de exibicao bloqueada
|
|
264
|
+
// lastFirstAccess: 1740000000000, // primeira vez que o widget foi exibido
|
|
265
|
+
// lastDisplay: 1741000000000, // ultima exibicao do widget
|
|
266
|
+
// lastDismiss: 1741000000000, // ultima vez que o usuario fechou
|
|
267
|
+
// lastSubmit: 0, // ultimo envio completo
|
|
268
|
+
// lastPartialSubmit: 0, // ultimo envio parcial
|
|
269
|
+
// }
|
|
97
270
|
```
|
|
98
271
|
|
|
99
|
-
|
|
272
|
+
### Exemplo 7: Sobrescrever datas de eventos (debug/teste)
|
|
100
273
|
|
|
101
|
-
|
|
274
|
+
Use `overrideTimestamp` para simular cenarios de teste sem esperar os dias reais.
|
|
102
275
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
| `soluCXKey` | `string` | ✅ | Chave de autenticação SoluCX |
|
|
106
|
-
| `type` | `WidgetType` | ✅ | Modo de renderização |
|
|
107
|
-
| `data` | `WidgetData` | ✅ | Dados do cliente/transação |
|
|
108
|
-
| `options` | `WidgetOptions` | ✅ | Configurações do widget |
|
|
276
|
+
```tsx
|
|
277
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
109
278
|
|
|
110
|
-
|
|
279
|
+
const widget = SoluCXWidget
|
|
280
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
281
|
+
.setData({ journey: 'pos_venda', user_id: 'user_123' });
|
|
111
282
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// Identificadores
|
|
115
|
-
transaction_id?: string;
|
|
116
|
-
customer_id?: string;
|
|
117
|
-
|
|
118
|
-
// Dados do cliente
|
|
119
|
-
name?: string;
|
|
120
|
-
email?: string;
|
|
121
|
-
phone?: string;
|
|
122
|
-
birth_date?: string; // Formato: YYYY-MM-DD
|
|
123
|
-
document?: string;
|
|
124
|
-
|
|
125
|
-
// Contexto da transação
|
|
126
|
-
store_id?: string;
|
|
127
|
-
store_name?: string;
|
|
128
|
-
employee_id?: string;
|
|
129
|
-
employee_name?: string;
|
|
130
|
-
amount?: number;
|
|
131
|
-
score?: number;
|
|
132
|
-
journey?: string; // Nome da jornada/fluxo
|
|
133
|
-
|
|
134
|
-
// Parâmetros customizados (prefixo param_)
|
|
135
|
-
param_REGIAO?: string;
|
|
136
|
-
[key: string]: string | number | undefined;
|
|
137
|
-
}
|
|
138
|
-
```
|
|
283
|
+
// Informar primeiro acesso do usuário
|
|
284
|
+
await widget.overrideTimestamp('lastFirstAccess', new Date('2026-01-01T00:00:00Z'));
|
|
139
285
|
|
|
140
|
-
|
|
286
|
+
// Ou usar timestamp em milissegundos diretamente
|
|
287
|
+
await widget.overrideTimestamp('lastFirstAccess', 1700000000000);
|
|
141
288
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
retry?: {
|
|
148
|
-
attempts?: number; // Tentativas (padrão: 3)
|
|
149
|
-
interval?: number; // Intervalo em ms (padrão: 1000)
|
|
150
|
-
};
|
|
151
|
-
waitDelayAfterRating?: number; // Delay após avaliação
|
|
152
|
-
}
|
|
289
|
+
// Resetar um campo para "nunca aconteceu" (valor 0)
|
|
290
|
+
await widget.overrideTimestamp('lastSubmit', 0);
|
|
291
|
+
|
|
292
|
+
// Depois de sobrescrever, pode exibir o widget normalmente
|
|
293
|
+
widget.show();
|
|
153
294
|
```
|
|
154
295
|
|
|
155
|
-
**
|
|
296
|
+
**Campos disponiveis para `overrideTimestamp`:**
|
|
156
297
|
|
|
157
|
-
|
|
298
|
+
| Campo | Descricao |
|
|
299
|
+
|---|---|
|
|
300
|
+
| `lastDisplayAttempt` | Ultima tentativa de exibicao (widget foi bloqueado) |
|
|
301
|
+
| `lastFirstAccess` | Primeira vez que o widget foi exibido para o usuario |
|
|
302
|
+
| `lastDisplay` | Ultima exibicao do widget |
|
|
303
|
+
| `lastDismiss` | Ultima vez que o usuario fechou o widget |
|
|
304
|
+
| `lastSubmit` | Ultimo envio completo da pesquisa |
|
|
305
|
+
| `lastPartialSubmit` | Ultimo envio parcial da pesquisa |
|
|
306
|
+
| `answeredTransactionIds` | Lista de `transaction_id` que ja responderam e devem ser bloqueados localmente |
|
|
158
307
|
|
|
159
|
-
|
|
160
|
-
// Altura dinâmica - se adapta ao conteúdo
|
|
161
|
-
<SoluCXWidget
|
|
162
|
-
type='bottom'
|
|
163
|
-
options={{}} // ou options={{ retry: { attempts: 3 } }}
|
|
164
|
-
{...props}
|
|
165
|
-
/>
|
|
166
|
-
```
|
|
308
|
+
### Exemplo 8: Limpar logs de supressao
|
|
167
309
|
|
|
168
|
-
|
|
310
|
+
```tsx
|
|
311
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
169
312
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
```
|
|
313
|
+
const widget = SoluCXWidget
|
|
314
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
315
|
+
.setData({ journey: 'pos_venda', user_id: 'user_123' });
|
|
174
316
|
|
|
175
|
-
|
|
317
|
+
// Limpar TODOS os logs (reseta contadores e timestamps)
|
|
318
|
+
await widget.clearWidgetLogs();
|
|
176
319
|
|
|
177
|
-
|
|
320
|
+
// Apos limpar, o widget vai se comportar como se nunca tivesse sido exibido
|
|
321
|
+
widget.show();
|
|
322
|
+
```
|
|
178
323
|
|
|
179
|
-
|
|
180
|
-
|
|
324
|
+
### Exemplo 9: Forcar exibicao do widget (ignorar bloqueio)
|
|
325
|
+
|
|
326
|
+
Se o widget esta sendo bloqueado por uma regra de supressao e voce quer forca-lo a exibir (por exemplo, para testes), sobrescreva a data do evento que esta bloqueando:
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
330
|
+
|
|
331
|
+
const widget = SoluCXWidget
|
|
332
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
333
|
+
.setData({ journey: 'pos_venda', user_id: 'user_123' });
|
|
334
|
+
|
|
335
|
+
// Verificar qual evento esta bloqueando
|
|
336
|
+
const logs = await widget.getWidgetLogs();
|
|
337
|
+
console.log('Ultimo dismiss:', new Date(logs.lastDismiss));
|
|
338
|
+
console.log('Tentativas:', logs.attempts);
|
|
339
|
+
|
|
340
|
+
// Resetar o dismiss para desbloquear
|
|
341
|
+
await widget.overrideTimestamp('lastDismiss', 0);
|
|
342
|
+
|
|
343
|
+
// Agora o widget vai exibir (se nao houver outra regra bloqueando)
|
|
344
|
+
widget.show();
|
|
181
345
|
```
|
|
182
346
|
|
|
183
|
-
|
|
347
|
+
### Exemplo 10: Isolamento por jornada — dois widgets independentes
|
|
184
348
|
|
|
185
|
-
|
|
349
|
+
Cada combinacao de `instanceKey + journey + userId` tem seus proprios logs. Widgets de jornadas diferentes nao interferem entre si.
|
|
186
350
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
- `FORM_COMPLETED` - Pesquisa concluída
|
|
190
|
-
- `FORM_PARTIALCOMPLETED` - Completada parcialmente
|
|
191
|
-
- `FORM_RESIZE` - Widget redimensionado
|
|
192
|
-
- `FORM_ERROR` - Erro no carregamento
|
|
351
|
+
```tsx
|
|
352
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
193
353
|
|
|
194
|
-
|
|
354
|
+
// Widget da jornada "pos_venda"
|
|
355
|
+
const widgetPosVenda = SoluCXWidget
|
|
356
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
357
|
+
.setData({ journey: 'pos_venda', user_id: 'user_123' });
|
|
195
358
|
|
|
196
|
-
|
|
359
|
+
// Widget da jornada "atendimento"
|
|
360
|
+
const widgetAtendimento = SoluCXWidget
|
|
361
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
362
|
+
.setData({ journey: 'atendimento', user_id: 'user_123' });
|
|
197
363
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
364
|
+
// Os logs sao independentes:
|
|
365
|
+
const logsPosVenda = await widgetPosVenda.getWidgetLogs();
|
|
366
|
+
const logsAtendimento = await widgetAtendimento.getWidgetLogs();
|
|
367
|
+
// logsPosVenda pode ter 5 tentativas enquanto logsAtendimento tem 0
|
|
368
|
+
|
|
369
|
+
// Limpar os logs de uma jornada NAO afeta a outra
|
|
370
|
+
await widgetPosVenda.clearWidgetLogs();
|
|
371
|
+
// Apenas os logs de pos_venda foram resetados
|
|
372
|
+
```
|
|
202
373
|
|
|
203
|
-
|
|
374
|
+
### Exemplo 11: Widget sem userId (dispositivo anonimo)
|
|
375
|
+
|
|
376
|
+
Quando nao ha `user_id`, `email` ou `cpf`, os logs sao compartilhados por todos os usuarios daquela jornada naquele dispositivo.
|
|
204
377
|
|
|
205
378
|
```tsx
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
379
|
+
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';
|
|
380
|
+
|
|
381
|
+
// Sem userId — logs sao por instanceKey:journey (compartilhado no dispositivo)
|
|
382
|
+
const widget = SoluCXWidget
|
|
383
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
384
|
+
.setData({ journey: 'pos_venda' });
|
|
385
|
+
|
|
386
|
+
const logs = await widget.getWidgetLogs();
|
|
387
|
+
// Chave de armazenamento: "SUA_CHAVE_SOLUCX:pos_venda"
|
|
388
|
+
|
|
389
|
+
// Com userId — logs sao por instanceKey:journey:userId (isolado por usuario)
|
|
390
|
+
const widgetComUser = SoluCXWidget
|
|
391
|
+
.create('SUA_CHAVE_SOLUCX')
|
|
392
|
+
.setData({ journey: 'pos_venda', user_id: 'user_123' });
|
|
393
|
+
|
|
394
|
+
const logsComUser = await widgetComUser.getWidgetLogs();
|
|
395
|
+
// Chave de armazenamento: "SUA_CHAVE_SOLUCX:pos_venda:user_123"
|
|
221
396
|
```
|
|
222
397
|
|
|
223
|
-
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Opcoes de Supressao (waitDays)
|
|
401
|
+
|
|
402
|
+
> **Importante:** Voce **nao precisa passar essas opcoes no codigo**. Elas podem (e devem) ser configuradas remotamente no painel de configuracao da jornada. O widget busca automaticamente as configuracoes da API quando `setOptions()` nao e chamado.
|
|
403
|
+
|
|
404
|
+
As opcoes controlam quantos dias o widget deve esperar apos cada tipo de evento antes de exibir novamente:
|
|
405
|
+
|
|
406
|
+
| Opcao | Descricao |
|
|
407
|
+
|---|---|
|
|
408
|
+
| `enabled` | Habilita/desabilita o widget. Quando `false`, bloqueia imediatamente sem validar outras regras |
|
|
409
|
+
| `samplingPercentage` | Porcentagem de usuarios que verao o widget (0-100). Valor 100 ou undefined = sem amostragem |
|
|
410
|
+
| `maxAttemptsAfterDismiss` | Numero maximo de tentativas de exibicao por experiencia |
|
|
411
|
+
| `waitDaysAfterWidgetDisplayAttempt` | Dias apos uma tentativa de exibicao bloqueada |
|
|
412
|
+
| `waitDaysAfterWidgetFirstAccess` | Dias apos o primeiro acesso do usuario a jornada |
|
|
413
|
+
| `waitDaysAfterWidgetDisplay` | Dias apos qualquer exibicao do widget |
|
|
414
|
+
| `waitDaysAfterWidgetDismiss` | Dias apos o usuario fechar o widget |
|
|
415
|
+
| `waitDaysAfterWidgetSubmit` | Dias apos o usuario responder a pesquisa |
|
|
416
|
+
| `waitDaysAfterWidgetPartialSubmit` | Dias apos o usuario responder parcialmente |
|
|
417
|
+
|
|
418
|
+
**Regras:**
|
|
419
|
+
- `enabled: false` bloqueia o widget **imediatamente** com `BLOCKED_BY_DISABLED`, sem verificar nenhuma outra regra
|
|
420
|
+
- `enabled: true` ou `undefined` = widget habilitado (comportamento padrao)
|
|
421
|
+
- `samplingPercentage`: sorteia se o usuario vera o widget. Ex: `50` = 50% de chance. Valor `100` ou `undefined` = todos veem. Valor `0` = ninguem ve
|
|
422
|
+
- Valor `0` ou `undefined` nos campos de dias = sem restricao (o campo nao bloqueia)
|
|
423
|
+
- Se **qualquer** regra bloquear, o widget nao exibe e chama `onBlocked(reason)`
|
|
424
|
+
- Quando bloqueado, o `reason` indica qual regra bloqueou (ex: `"BLOCKED_BY_WIDGET_DISMISS_INTERVAL"`)
|
|
425
|
+
- `maxAttemptsAfterDismiss` conta quantas vezes o widget foi exibido para aquela experiencia (jornada). Se o ID da experiencia (`journey` ou `form_id`) mudar, o contador de tentativas e resetado automaticamente
|
|
426
|
+
- Quando o usuario engaja na pesquisa (`QUESTION_ANSWERED`, envio completo ou envio parcial), o contador de tentativas tambem e resetado para nao bloquear exibicoes futuras por tentativas antigas
|
|
427
|
+
- Quando existe `transaction_id` e essa transacao ja foi concluida ou parcialmente concluida antes, o widget bloqueia localmente e nao faz chamadas de opcoes nem de preflight
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## API Completa
|
|
432
|
+
|
|
433
|
+
### `SoluCXWidget` (classe principal)
|
|
434
|
+
|
|
435
|
+
#### Metodos de construcao (builder pattern)
|
|
436
|
+
|
|
437
|
+
| Metodo | Descricao |
|
|
438
|
+
|---|---|
|
|
439
|
+
| `SoluCXWidget.create(soluCXKey)` | Cria uma nova instancia do widget |
|
|
440
|
+
| `.setType(type)` | Define o tipo: `'bottom'`, `'top'`, `'modal'`, `'inline'` |
|
|
441
|
+
| `.setData(data)` | Define os dados do usuario/transacao |
|
|
442
|
+
| `.setOptions(options)` | Define opcoes locais (**opcional** - se nao chamar, busca da API) |
|
|
443
|
+
| `.setCallbacks(callbacks)` | Define callbacks de eventos |
|
|
444
|
+
| `.show()` | Exibe o widget |
|
|
445
|
+
|
|
446
|
+
#### Metodos estaticos
|
|
447
|
+
|
|
448
|
+
| Metodo | Descricao |
|
|
449
|
+
|---|---|
|
|
450
|
+
| `SoluCXWidget.dismiss()` | Fecha o widget programaticamente |
|
|
224
451
|
|
|
225
|
-
|
|
452
|
+
#### Metodos de instancia (log management)
|
|
226
453
|
|
|
227
|
-
|
|
454
|
+
Usam os dados do builder (instanceKey, journey, userId) para acessar os logs da combinacao correta.
|
|
455
|
+
|
|
456
|
+
| Metodo | Descricao |
|
|
457
|
+
|---|---|
|
|
458
|
+
| `.getWidgetLogs()` | Retorna os logs de supressao |
|
|
459
|
+
| `.overrideTimestamp(field, date)` | Sobrescreve uma data de evento (debug/teste) |
|
|
460
|
+
| `.clearWidgetLogs()` | Limpa todos os logs |
|
|
461
|
+
|
|
462
|
+
> **Isolamento de armazenamento:** Os logs sao isolados por `instanceKey:journey:userId`. Um app com 2 widgets de jornadas diferentes tera dados de supressao independentes. O `userId` e opcional — quando presente, os logs sao por usuario.
|
|
463
|
+
|
|
464
|
+
### `SoluCXWidgetHost` (componente React)
|
|
465
|
+
|
|
466
|
+
Componente que deve ser montado **uma vez** no root do app quando a integracao for feita por funcao com `SoluCXWidget.create(...).show()`. Nao e necessario ao usar `SoluCXWidgetView` diretamente.
|
|
228
467
|
|
|
229
468
|
```tsx
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<
|
|
234
|
-
|
|
235
|
-
// ✅ Apenas "inline" respeita a posição no código
|
|
236
|
-
<Text>Conteúdo antes</Text>
|
|
237
|
-
<SoluCXWidget type="inline" {...props} />
|
|
238
|
-
<Text>Conteúdo depois</Text>
|
|
469
|
+
import { SoluCXWidgetHost } from '@solucx/react-native-solucx-widget';
|
|
470
|
+
|
|
471
|
+
// No root do app
|
|
472
|
+
<SoluCXWidgetHost />
|
|
239
473
|
```
|
|
240
474
|
|
|
241
|
-
|
|
475
|
+
### `SoluCXWidgetView` (componente React)
|
|
242
476
|
|
|
243
|
-
|
|
477
|
+
Componente para uso direto no JSX. Pode ser usado no lugar do fluxo por funcao quando fizer mais sentido controlar a renderizacao pelo componente.
|
|
244
478
|
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
479
|
+
```tsx
|
|
480
|
+
import { SoluCXWidgetView } from '@solucx/react-native-solucx-widget';
|
|
481
|
+
|
|
482
|
+
<SoluCXWidgetView
|
|
483
|
+
soluCXKey="SUA_CHAVE_SOLUCX"
|
|
484
|
+
type="inline"
|
|
485
|
+
data={{ journey: 'pos_venda', user_id: 'user_123' }}
|
|
486
|
+
/>
|
|
251
487
|
```
|
|
252
488
|
|
|
253
|
-
|
|
489
|
+
**Props:**
|
|
490
|
+
|
|
491
|
+
| Prop | Descricao |
|
|
492
|
+
|---|---|
|
|
493
|
+
| `soluCXKey` | Chave de instancia do widget |
|
|
494
|
+
| `type` | Tipo do widget: `'bottom'`, `'top'`, `'modal'`, `'inline'` |
|
|
495
|
+
| `data` | Dados do usuario/transacao |
|
|
496
|
+
| `options` | Opcoes locais de configuracao e supressao |
|
|
497
|
+
| `callbacks` | Callbacks de ciclo de vida e eventos |
|
|
498
|
+
|
|
499
|
+
### WidgetData
|
|
254
500
|
|
|
255
501
|
```typescript
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
502
|
+
interface WidgetData {
|
|
503
|
+
journey?: string; // Nome da jornada (obrigatorio na pratica)
|
|
504
|
+
user_id?: string; // ID do usuario
|
|
505
|
+
email?: string; // Email do usuario
|
|
506
|
+
name?: string; // Nome do usuario
|
|
507
|
+
cpf?: string; // CPF
|
|
508
|
+
document?: string; // Documento
|
|
509
|
+
phone?: string; // Telefone
|
|
510
|
+
phone2?: string; // Telefone secundario
|
|
511
|
+
birth_date?: string; // Data de nascimento (YYYY-MM-DD)
|
|
512
|
+
transaction_id?: string; // ID da transacao
|
|
513
|
+
customer_id?: string; // ID do cliente
|
|
514
|
+
store_id?: string; // ID da loja
|
|
515
|
+
store_name?: string; // Nome da loja
|
|
516
|
+
employee_id?: string; // ID do funcionario
|
|
517
|
+
employee_name?: string; // Nome do funcionario
|
|
518
|
+
amount?: number; // Valor da transacao
|
|
519
|
+
score?: number; // Score
|
|
520
|
+
[key: `param_${string}`]: string | number | undefined; // Parametros customizados
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### WidgetCallbacks
|
|
260
525
|
|
|
261
|
-
|
|
526
|
+
```typescript
|
|
527
|
+
interface WidgetCallbacks {
|
|
528
|
+
onPreOpen?: (userId: string) => void; // Antes de abrir
|
|
529
|
+
onOpened?: (userId: string) => void; // Widget aberto
|
|
530
|
+
onBlocked?: (reason: BlockReason) => void; // Widget bloqueado por regra de supressao
|
|
531
|
+
onClosed?: () => void; // Usuario fechou
|
|
532
|
+
onCompleted?: (userId: string) => void; // Pesquisa respondida
|
|
533
|
+
onPartialCompleted?: (userId: string) => void; // Pesquisa parcialmente respondida
|
|
534
|
+
onError?: (message: string) => void; // Erro no widget
|
|
535
|
+
onPageChanged?: (page: string) => void; // Pagina mudou
|
|
536
|
+
onQuestionAnswered?: () => void; // Pergunta respondida
|
|
537
|
+
onResize?: (height: string) => void; // Widget redimensionou
|
|
538
|
+
}
|
|
262
539
|
```
|
|
263
540
|
|
|
264
|
-
###
|
|
541
|
+
### WidgetOptions
|
|
265
542
|
|
|
266
543
|
```typescript
|
|
267
|
-
|
|
268
|
-
|
|
544
|
+
interface WidgetOptions {
|
|
545
|
+
enabled?: boolean; // Habilita/desabilita o widget (default: true). Quando false, bloqueia sem validar.
|
|
546
|
+
samplingPercentage?: number; // Porcentagem de usuarios que verao o widget (0-100). Default: 100 (todos).
|
|
547
|
+
height?: number; // Altura fixa em pontos (se nao informado, altura dinamica)
|
|
548
|
+
maxAttemptsAfterDismiss?: number; // Maximo de tentativas por experiencia (0 ou undefined = sem limite)
|
|
549
|
+
// Regras de supressao (opcionais - configuradas remotamente pelo painel da jornada):
|
|
550
|
+
waitDaysAfterWidgetDisplayAttempt?: number;
|
|
551
|
+
waitDaysAfterWidgetFirstAccess?: number;
|
|
552
|
+
waitDaysAfterWidgetDisplay?: number;
|
|
553
|
+
waitDaysAfterWidgetDismiss?: number;
|
|
554
|
+
waitDaysAfterWidgetSubmit?: number;
|
|
555
|
+
waitDaysAfterWidgetPartialSubmit?: number;
|
|
556
|
+
}
|
|
557
|
+
```
|
|
269
558
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
559
|
+
### BlockReason
|
|
560
|
+
|
|
561
|
+
Valores possiveis retornados no callback `onBlocked`:
|
|
562
|
+
|
|
563
|
+
| Valor | Significado |
|
|
564
|
+
|---|---|
|
|
565
|
+
| `BLOCKED_BY_DISABLED` | Widget desabilitado (enabled: false) |
|
|
566
|
+
| `BLOCKED_BY_SAMPLING` | Usuario nao foi selecionado pela amostragem (samplingPercentage) |
|
|
567
|
+
| `BLOCKED_BY_MAX_ATTEMPTS` | Numero maximo de tentativas atingido para esta experiencia |
|
|
568
|
+
| `BLOCKED_BY_WIDGET_DISPLAY_ATTEMPT_INTERVAL` | Dentro do intervalo apos tentativa de exibicao |
|
|
569
|
+
| `BLOCKED_BY_WIDGET_FIRST_ACCESS_INTERVAL` | Dentro do intervalo apos primeira visualizacao |
|
|
570
|
+
| `BLOCKED_BY_WIDGET_DISPLAY_INTERVAL` | Dentro do intervalo apos exibicao |
|
|
571
|
+
| `BLOCKED_BY_WIDGET_DISMISS_INTERVAL` | Dentro do intervalo apos fechamento |
|
|
572
|
+
| `BLOCKED_BY_WIDGET_SUBMIT_INTERVAL` | Dentro do intervalo apos envio completo |
|
|
573
|
+
| `BLOCKED_BY_WIDGET_PARTIAL_SUBMIT_INTERVAL` | Dentro do intervalo apos envio parcial |
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## Fluxo Interno
|
|
578
|
+
|
|
579
|
+
```
|
|
580
|
+
App chama SoluCXWidget.create('KEY').setData({...}).show()
|
|
581
|
+
|
|
|
582
|
+
v
|
|
583
|
+
SoluCXWidgetHost recebe a configuracao
|
|
584
|
+
|
|
|
585
|
+
v
|
|
586
|
+
Widget monta e executa bootstrap():
|
|
587
|
+
|
|
|
588
|
+
+-- Se setOptions() FOI chamado --> usa opcoes locais
|
|
589
|
+
+-- Se setOptions() NAO foi chamado --> busca opcoes da API (painel da jornada)
|
|
590
|
+
|
|
|
591
|
+
+-- shouldDisplayWidget() verifica enabled + maxAttemptsAfterDismiss + 6 regras de supressao
|
|
592
|
+
+-- (validacao LOCAL, antes de chamar a API, para reduzir carga no servidor):
|
|
593
|
+
| +-- Se transaction_id ja respondido --> onBlocked('BLOCKED_BY_TRANSACTION_ALREADY_ANSWERED'), widget NAO exibe
|
|
594
|
+
| +-- Se enabled === false --> onBlocked('BLOCKED_BY_DISABLED'), widget NAO exibe
|
|
595
|
+
| +-- Sorteia baseado em samplingPercentage --> se nao selecionado, onBlocked('BLOCKED_BY_SAMPLING')
|
|
596
|
+
| +-- Se experiencia mudou --> reseta contador de tentativas
|
|
597
|
+
| +-- Se tentativas >= maxAttemptsAfterDismiss --> onBlocked('BLOCKED_BY_MAX_ATTEMPTS')
|
|
598
|
+
| +-- Para cada regra: timestamp do evento + dias de espera > agora?
|
|
599
|
+
| +-- Se QUALQUER regra bloqueia --> onBlocked(reason), widget NAO exibe
|
|
600
|
+
| +-- Se NENHUMA bloqueia --> continua
|
|
601
|
+
|
|
|
602
|
+
+-- Busca URL do formulario na API (preflight)
|
|
603
|
+
|
|
|
604
|
+
+-- Se EXIBE:
|
|
605
|
+
| +-- Incrementa contador de tentativas
|
|
606
|
+
| +-- Salva lastDisplay (e lastFirstAccess na primeira vez)
|
|
607
|
+
| +-- Renderiza WebView com o formulario
|
|
608
|
+
| +-- onOpened(userId)
|
|
609
|
+
|
|
|
610
|
+
+-- Eventos do usuario:
|
|
611
|
+
+-- Fecha widget --> salva lastDismiss, onClosed()
|
|
612
|
+
+-- Responde pergunta --> zera contador de tentativas, onQuestionAnswered()
|
|
613
|
+
+-- Responde pesquisa --> zera contador de tentativas, salva transaction_id respondido, salva lastSubmit, onCompleted(userId)
|
|
614
|
+
+-- Resposta parcial --> zera contador de tentativas, salva transaction_id respondido, salva lastPartialSubmit, onPartialCompleted(userId)
|
|
273
615
|
```
|
|
274
616
|
|
|
275
|
-
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## Compatibilidade
|
|
276
620
|
|
|
277
|
-
|
|
|
278
|
-
|
|
279
|
-
| 1.0.x
|
|
621
|
+
| Versao | React Native | Expo | iOS | Android |
|
|
622
|
+
|---|---|---|---|---|
|
|
623
|
+
| 1.0.x | 0.70+ | 50+ | 11+ | API 21+ |
|
|
280
624
|
|
|
281
|
-
##
|
|
625
|
+
## Licenca
|
|
282
626
|
|
|
283
|
-
|
|
627
|
+
Proprietario - SoluCX. Uso restrito a clientes licenciados.
|
|
284
628
|
|
|
285
629
|
---
|