@pensasystems/pensa-react-native 0.1.0-beta.1 → 0.1.0

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.
@@ -21,5 +21,5 @@ Pod::Spec.new do |s|
21
21
  s.dependency "React-Core"
22
22
  end
23
23
 
24
- s.dependency "PensaSdk", "~> 1.0.4"
24
+ s.dependency "PensaSdk", "~> 1.1.3"
25
25
  end
package/README.md CHANGED
@@ -7,17 +7,18 @@ The Pensa Mobile App SDK is a developer toolkit designed to simplify adding Pens
7
7
  Integrating the Pensa SDK into your React Native project is simple. Follow the steps below to add the SDK and enable advanced shelf recognition features in your app:
8
8
 
9
9
  ### 1- Install the SDK Package
10
+ Registry: https://www.npmjs.com/package/@pensasystems/pensa-react-native
10
11
 
11
12
  Add the npm package to your project:
12
13
 
13
14
  ```bash
14
- npm install pensa-sdk-react-native
15
+ npm install @pensasystems/pensa-react-native
15
16
  ```
16
17
 
17
18
  or
18
19
 
19
20
  ```bash
20
- yarn add pensa-sdk-react-native
21
+ yarn add @pensasystems/pensa-react-native
21
22
  ```
22
23
 
23
24
  ### 2- Install Native Dependencies (iOS)
@@ -44,7 +45,7 @@ Initializing the Pensa SDK is straightforward. Follow the steps below to set up
44
45
  Call `initPensa()` at the startup of your app, preferably in a root file like `index.js` before calling `AppRegistry.registerComponent`.
45
46
 
46
47
  ```tsx
47
- import {initPensa} from 'pensa-sdk-react-native';
48
+ import {initPensa} from '@pensasystems/pensa-react-native';
48
49
 
49
50
  initPensa({
50
51
  clientId: 'YOUR_CLIENT_ID',
@@ -71,7 +72,7 @@ To listen to SDK events such as upload progress, success, or failure, you can cr
71
72
  ```tsx
72
73
  // hooks/usePensaListeners.ts
73
74
  import {useEffect} from 'react';
74
- import {PensaEvents} from 'pensa-sdk-react-native';
75
+ import {PensaEvents} from '@pensasystems/pensa-react-native';
75
76
 
76
77
  export const usePensaListeners = () => {
77
78
  useEffect(() => {
@@ -151,7 +152,7 @@ import {
151
152
  showScanArea,
152
153
  showStockingScreen,
153
154
  showStoreChecklist,
154
- } from 'pensa-sdk-react-native';
155
+ } from '@pensasystems/pensa-react-native';
155
156
  ```
156
157
 
157
158
  ### Searching stores
@@ -273,6 +274,99 @@ showScanArea(scanId, storeId, globalStoreId)
273
274
 
274
275
  This method allows you to navigate directly to a scan area without going through the store selection flow.
275
276
 
277
+ # Troubleshooting (Android)
278
+
279
+ ## 1. Core Library Desugaring Required
280
+
281
+ If you see an error mentioning that `core library desugaring` must be enabled (typically referencing `AAR metadata` or `desugar_jdk_libs`), update your Android project as follows:
282
+
283
+ ### **Step 1 — Add desugaring dependency**
284
+
285
+ In your app-level `build.gradle`:
286
+
287
+ ```gradle
288
+ dependencies {
289
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
290
+ }
291
+ ```
292
+
293
+ ### **Step 2 — Enable desugaring & set Java 17**
294
+
295
+ Inside `android { compileOptions { ... } }`:
296
+
297
+ ```gradle
298
+ compileOptions {
299
+ sourceCompatibility JavaVersion.VERSION_17
300
+ targetCompatibility JavaVersion.VERSION_17
301
+ coreLibraryDesugaringEnabled true
302
+ }
303
+ ```
304
+
305
+ This configuration is required because the native Pensa Android SDK uses Java 17 language features.
306
+
307
+ ---
308
+
309
+ ## 2. Min SDK Version Requirement
310
+
311
+ If your Android build fails with a message indicating:
312
+
313
+ > *minSdkVersion cannot be smaller than 26 for library com.pensasystems:pensasdk*
314
+
315
+ Then your `minSdkVersion` must be updated.
316
+
317
+ ### **Fix**
318
+
319
+ In your app-level `build.gradle`:
320
+
321
+ ```gradle
322
+ defaultConfig {
323
+ minSdkVersion 26
324
+ }
325
+ ```
326
+
327
+ The native Pensa Android SDK requires **minSdk 26**.
328
+
329
+ ---
330
+
331
+ ## 3. Metro Bundler Cannot Connect in Debug Mode (Android Only)
332
+
333
+ If the Android app cannot connect to Metro (e.g., blank screen, “Unable to load script from assets”), update your debug network rules.
334
+
335
+ ### **Step 1 — Create `network_security_config.xml`**
336
+
337
+ Create a file:
338
+
339
+ ```
340
+ android/app/src/main/res/xml/network_security_config.xml
341
+ ```
342
+
343
+ With the following content:
344
+
345
+ ```xml
346
+ <?xml version="1.0" encoding="utf-8"?>
347
+ <network-security-config>
348
+ <domain-config cleartextTrafficPermitted="true">
349
+ <domain includeSubdomains="true">10.0.2.2</domain>
350
+ <domain includeSubdomains="true">localhost</domain>
351
+ <domain includeSubdomains="true">127.0.0.1</domain>
352
+ </domain-config>
353
+ </network-security-config>
354
+ ```
355
+
356
+ ### **Step 2 — Reference it in `AndroidManifest.xml`**
357
+
358
+ Inside your `<application>` tag:
359
+
360
+ ```xml
361
+ <application
362
+ android:networkSecurityConfig="@xml/network_security_config"
363
+ ... >
364
+ ```
365
+
366
+ This allows the Android emulator to access the React Native bundler during development.
367
+
368
+ ---
369
+
276
370
  ### Example Project
277
371
 
278
372
  For code examples and integration best practices, refer to our GitHub repository.
@@ -83,7 +83,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
83
83
 
84
84
  dependencies {
85
85
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
86
- implementation "com.pensasystems:pensasdk:1.0.8"
86
+ implementation "com.pensasystems:pensasdk:1.0.22"
87
87
  implementation "com.facebook.react:react-android"
88
88
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
89
89
  }
@@ -1,14 +1,17 @@
1
1
  package com.pensasdkreactnative
2
2
 
3
+ import com.facebook.react.bridge.Arguments
3
4
  import com.facebook.react.bridge.ReactApplicationContext
4
5
  import com.facebook.react.bridge.ReactContextBaseJavaModule
5
6
  import com.facebook.react.bridge.ReactMethod
6
7
  import com.facebook.react.bridge.Promise
8
+ import com.facebook.react.bridge.ReadableArray
7
9
  import com.facebook.react.bridge.ReadableMap
10
+ import com.facebook.react.bridge.ReadableType
8
11
  import com.pensasystems.pensasdk.PensaSdk
9
12
  import com.pensasystems.pensasdk.PensaSdkConfiguration
10
- import com.pensasystems.pensasdk.listener.CantScanEventListener
11
- import com.pensasystems.pensasdk.listener.ScanUploadListener
13
+ import com.pensasystems.pensasdk.model.PensaReportType
14
+ import com.pensasystems.pensasdk.model.PensaShelfItem
12
15
 
13
16
  class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
14
17
  ReactContextBaseJavaModule(reactContext) {
@@ -69,7 +72,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
69
72
 
70
73
  @ReactMethod
71
74
  fun showShelfScans(promise: Promise) {
72
- val activity = currentActivity
75
+ val activity = reactApplicationContext.currentActivity
73
76
  if (activity != null) {
74
77
  PensaSdk.showShelfScans(
75
78
  context = activity,
@@ -82,7 +85,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
82
85
  }
83
86
  @ReactMethod
84
87
  fun showProductScans(promise: Promise) {
85
- val activity = currentActivity
88
+ val activity = reactApplicationContext.currentActivity
86
89
  if (activity != null) {
87
90
  PensaSdk.showProductScans(
88
91
  context = activity,
@@ -96,7 +99,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
96
99
 
97
100
  @ReactMethod
98
101
  fun showStoreSearchView(promise: Promise) {
99
- val activity = currentActivity
102
+ val activity = reactApplicationContext.currentActivity
100
103
  if (activity != null) {
101
104
  PensaSdk.showStoreSearchView(
102
105
  context = activity,
@@ -110,7 +113,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
110
113
 
111
114
  @ReactMethod
112
115
  fun showStoresScreen(promise: Promise) {
113
- val activity = currentActivity
116
+ val activity = reactApplicationContext.currentActivity
114
117
  if (activity != null) {
115
118
  PensaSdk.showStoresScreen(
116
119
  context = activity,
@@ -124,7 +127,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
124
127
 
125
128
  @ReactMethod
126
129
  fun showScanArea(scanId: Int, storeId: Int?, globalStoreId: String?, promise: Promise) {
127
- val activity = currentActivity
130
+ val activity = reactApplicationContext.currentActivity
128
131
  if (activity != null) {
129
132
  PensaSdk.showScanArea(
130
133
  context = activity,
@@ -141,7 +144,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
141
144
 
142
145
  @ReactMethod
143
146
  fun showStockingScreen(promise: Promise) {
144
- val activity = currentActivity
147
+ val activity = reactApplicationContext.currentActivity
145
148
  if (activity != null) {
146
149
  PensaSdk.showStockingScreen(
147
150
  context = activity,
@@ -155,7 +158,7 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
155
158
 
156
159
  @ReactMethod
157
160
  fun showStoreChecklist(globalStoreId: String, guid: String?, sectionKey: String?, promise: Promise) {
158
- val activity = currentActivity
161
+ val activity = reactApplicationContext.currentActivity
159
162
  if (activity != null) {
160
163
  PensaSdk.showStoreChecklist(
161
164
  context = activity,
@@ -169,4 +172,203 @@ class PensaSdkReactNativeModule(reactContext: ReactApplicationContext) :
169
172
  promise.reject("NO_ACTIVITY", "Current activity is null")
170
173
  }
171
174
  }
175
+
176
+ @ReactMethod
177
+ fun fetchScanStatuses(scanIds: ReadableArray, promise: Promise) {
178
+ try {
179
+ val ids = mutableListOf<Int>()
180
+ for (i in 0 until scanIds.size()) {
181
+ ids.add(scanIds.getInt(i))
182
+ }
183
+
184
+ PensaSdk.fetchScanStatuses(
185
+ scanIds = ids,
186
+ onSuccess = { statuses ->
187
+ val rnList = statuses.map { status ->
188
+ val map = Arguments.createMap()
189
+ map.putInt("id", status.id)
190
+ map.putString("created", status.created)
191
+ map.putString("fastStatus", status.fastStatus)
192
+ map.putString("scanTimestamp", status.scanTimestamp)
193
+ map.putString("scannerId", status.scannerId)
194
+ map.putString("status", status.status)
195
+
196
+ val metadata = Arguments.createMap()
197
+ metadata.putString("guid", status.metadata?.guid)
198
+ metadata.putString("serverUploadStarted", status.metadata?.serverUploadStarted)
199
+ map.putMap("metadata", metadata)
200
+
201
+ map
202
+ }
203
+
204
+ val result = Arguments.createArray()
205
+ rnList.forEach { result.pushMap(it) }
206
+ promise.resolve(result)
207
+
208
+ },
209
+ onError = { error ->
210
+ promise.reject("FETCH_SCAN_STATUSES_FAILED", error)
211
+ }
212
+ )
213
+ } catch (e: Exception) {
214
+ promise.reject("FETCH_SCAN_STATUSES_EXCEPTION", e)
215
+ }
216
+ }
217
+
218
+ @ReactMethod
219
+ fun fetchOnDemandReports(
220
+ scanId: Int,
221
+ projectId: Int?,
222
+ reportTypes: ReadableArray?,
223
+ promise: Promise
224
+ ) {
225
+ try {
226
+ val finalReportTypes = parseReportTypes(reportTypes)
227
+
228
+ PensaSdk.fetchOnDemandReports(
229
+ scanId = scanId,
230
+ projectId = projectId,
231
+ reportTypes = finalReportTypes,
232
+ onSuccess = { report ->
233
+ val result = Arguments.createMap()
234
+
235
+ fun toProductMap(p: com.pensasystems.pensasdk.model.PensaOnDemandProduct) =
236
+ Arguments.createMap().apply {
237
+ putString("brand", p.brand)
238
+ p.brandId?.let { putInt("brandId", it) } ?: putNull("brandId")
239
+
240
+ putString("category", p.category)
241
+ p.categoryId?.let { putInt("categoryId", it) } ?: putNull("categoryId")
242
+
243
+ p.expectedFacings?.let { putInt("expectedFacings", it) } ?: putNull("expectedFacings")
244
+ p.facings?.let { putInt("facings", it) } ?: putNull("facings")
245
+
246
+ putString("manufacturer", p.manufacturer)
247
+ p.manufacturerId?.let { putInt("manufacturerId", it) } ?: putNull("manufacturerId")
248
+
249
+ putString("product", p.product)
250
+ p.productId?.let { putInt("productId", it) } ?: putNull("productId")
251
+
252
+ putString("upc", p.upc)
253
+ }
254
+
255
+ fun toBucketMap(b: com.pensasystems.pensasdk.model.PensaOnDemandReportBucket) =
256
+ Arguments.createMap().apply {
257
+ val arr = Arguments.createArray()
258
+ b.productList.forEach { arr.pushMap(toProductMap(it)) }
259
+ putArray("productList", arr)
260
+ }
261
+
262
+ fun putBucket(key: String, bucket: com.pensasystems.pensasdk.model.PensaOnDemandReportBucket?) {
263
+ if (bucket == null) result.putNull(key) else result.putMap(key, toBucketMap(bucket))
264
+ }
265
+
266
+ // Fill only requested
267
+ finalReportTypes.distinct().forEach { t ->
268
+ when (t) {
269
+ PensaReportType.FACINGS_SEEN -> putBucket("facingsSeen", report.facingsSeen)
270
+ PensaReportType.FULL_FACINGS -> putBucket("fullFacings", report.fullFacings)
271
+ PensaReportType.FULL_FACINGS_AND_PRODUCT_POSITIONS ->
272
+ putBucket("fullFacingsAndProductPositions", report.fullFacingsAndProductPositions)
273
+ PensaReportType.ITEMS_SEEN -> putBucket("itemsSeen", report.itemsSeen)
274
+ PensaReportType.NEW_PRODUCTS -> putBucket("newProducts", report.newProducts)
275
+ PensaReportType.NEW_PRODUCT_PACKAGING -> putBucket("newProductPackaging", report.newProductPackaging)
276
+ PensaReportType.NO_OOS -> putBucket("noOos", report.noOos)
277
+ PensaReportType.OOS -> putBucket("oos", report.oos)
278
+ PensaReportType.PRODUCT_POSITIONS -> putBucket("productPositions", report.productPositions)
279
+ PensaReportType.SCAN_FAILED -> putBucket("scanFailed", report.scanFailed)
280
+ PensaReportType.SCAN_REJECTED -> putBucket("scanRejected", report.scanRejected)
281
+ PensaReportType.SCAN_SKIPPED -> putBucket("scanSkipped", report.scanSkipped)
282
+ }
283
+ }
284
+
285
+ // Other fields
286
+ report.projectId?.let { result.putInt("projectId", it) } ?: result.putNull("projectId")
287
+ result.putString("projectName", report.projectName)
288
+ report.projectReportId?.let { result.putInt("projectReportId", it) } ?: result.putNull("projectReportId")
289
+ result.putString("projectReportName", report.projectReportName)
290
+ result.putString("realogramSignedUrl", report.realogramSignedUrl)
291
+ report.shelfId?.let { result.putInt("shelfId", it) } ?: result.putNull("shelfId")
292
+ result.putString("shelfName", report.shelfName)
293
+ result.putString("status", report.status)
294
+
295
+ promise.resolve(result)
296
+ },
297
+ onError = { error ->
298
+ promise.reject("FETCH_ON_DEMAND_REPORTS_FAILED", error)
299
+ }
300
+ )
301
+ } catch (e: Exception) {
302
+ promise.reject("ON_DEMAND_EXCEPTION", e)
303
+ }
304
+ }
305
+
306
+ @ReactMethod
307
+ fun fetchProductImageBase64(productId: Int, promise: Promise) {
308
+ try {
309
+ val activity = reactApplicationContext.currentActivity
310
+ if (activity != null) {
311
+ PensaSdk.fetchProductImageBase64(
312
+ context = activity,
313
+ productId = productId,
314
+ onSuccess = { base64 ->
315
+ promise.resolve(base64)
316
+ },
317
+ onError = { error ->
318
+ promise.reject("FETCH_PRODUCT_IMAGE_FAILED", error)
319
+ }
320
+ )
321
+ } else {
322
+ promise.reject("NO_ACTIVITY", "Current activity is null")
323
+ }
324
+ } catch (e: Exception) {
325
+ promise.reject("FETCH_PRODUCT_IMAGE_EXCEPTION", e)
326
+ }
327
+ }
328
+
329
+ @ReactMethod
330
+ fun fetchShelves(globalStoreId: String, promise: Promise) {
331
+ try {
332
+ PensaSdk.fetchShelves(
333
+ globalStoreId = globalStoreId,
334
+ onSuccess = { shelves ->
335
+ val result = Arguments.createArray()
336
+
337
+ shelves.forEach { shelf ->
338
+ val map = Arguments.createMap()
339
+ map.putInt("id", shelf.id)
340
+ map.putString("name", shelf.name)
341
+ result.pushMap(map)
342
+ }
343
+
344
+ promise.resolve(result)
345
+ },
346
+ onError = { error ->
347
+ promise.reject("FETCH_SHELVES_FAILED", error)
348
+ }
349
+ )
350
+ } catch (e: Exception) {
351
+ promise.reject("FETCH_SHELVES_EXCEPTION", e)
352
+ }
353
+ }
354
+
355
+ // Helpers
356
+
357
+ private fun parseReportTypes(reportTypes: ReadableArray?): List<PensaReportType> {
358
+ if (reportTypes == null || reportTypes.size() == 0) return listOf(PensaReportType.ITEMS_SEEN)
359
+
360
+ val list = mutableListOf<PensaReportType>()
361
+ for (i in 0 until reportTypes.size()) {
362
+ if (reportTypes.getType(i) != ReadableType.String) continue
363
+ val raw = reportTypes.getString(i) ?: continue
364
+ val parsed = try {
365
+ PensaReportType.valueOf(raw)
366
+ } catch (e: Exception) {
367
+ null
368
+ }
369
+ if (parsed != null) list.add(parsed)
370
+ }
371
+
372
+ return if (list.isEmpty()) listOf(PensaReportType.ITEMS_SEEN) else list.distinct()
373
+ }
172
374
  }
@@ -37,6 +37,10 @@ RCT_EXTERN_METHOD(showStoreChecklist:(NSString *)globalStoreId
37
37
  withResolver:(RCTPromiseResolveBlock)resolve
38
38
  withRejecter:(RCTPromiseRejectBlock)reject)
39
39
 
40
+ RCT_EXTERN_METHOD(fetchShelves:(NSString *)globalStoreId
41
+ withResolver:(RCTPromiseResolveBlock)resolve
42
+ withRejecter:(RCTPromiseRejectBlock)reject)
43
+
40
44
  @end
41
45
 
42
46
  @interface RCT_EXTERN_MODULE(PensaEventEmitter, RCTEventEmitter)
@@ -37,6 +37,25 @@ RCT_EXTERN_METHOD(showStoreChecklist:(NSString *)globalStoreId
37
37
  withResolver:(RCTPromiseResolveBlock)resolve
38
38
  withRejecter:(RCTPromiseRejectBlock)reject)
39
39
 
40
+ RCT_EXTERN_METHOD(fetchScanStatuses:(NSArray *)scanIds
41
+ withResolver:(RCTPromiseResolveBlock)resolve
42
+ withRejecter:(RCTPromiseRejectBlock)reject)
43
+
44
+
45
+ RCT_EXTERN_METHOD(fetchOnDemandReports:(nonnull NSNumber *)scanId
46
+ projectId:(nullable NSNumber *)projectId
47
+ reportTypes:(nullable NSArray *)reportTypes
48
+ withResolver:(RCTPromiseResolveBlock)resolve
49
+ withRejecter:(RCTPromiseRejectBlock)reject)
50
+
51
+ RCT_EXTERN_METHOD(fetchProductImageBase64:(nonnull NSNumber *)productId
52
+ withResolver:(RCTPromiseResolveBlock)resolve
53
+ withRejecter:(RCTPromiseRejectBlock)reject)
54
+
55
+ RCT_EXTERN_METHOD(fetchShelves:(NSString *)globalStoreId
56
+ withResolver:(RCTPromiseResolveBlock)resolve
57
+ withRejecter:(RCTPromiseRejectBlock)reject)
58
+
40
59
  + (BOOL)requiresMainQueueSetup
41
60
  {
42
61
  return NO;
@@ -118,4 +118,173 @@ class PensaSdkReactNative: NSObject {
118
118
  resolve(nil)
119
119
  }
120
120
  }
121
+
122
+ @objc(fetchScanStatuses:withResolver:withRejecter:)
123
+ func fetchScanStatuses(
124
+ scanIds: [NSNumber],
125
+ resolve: @escaping RCTPromiseResolveBlock,
126
+ reject: @escaping RCTPromiseRejectBlock
127
+ ) {
128
+ let ids = scanIds.map { $0.intValue }
129
+
130
+ Pensa.shared.fetchScanStatuses(
131
+ scanIds: ids,
132
+ onSuccess: { statuses in
133
+ let mapped: [[String: Any]] = statuses.map { status in
134
+ var dict: [String: Any] = [:]
135
+
136
+ dict["id"] = status.id
137
+ dict["created"] = status.created ?? NSNull()
138
+ dict["fastStatus"] = status.fastStatus ?? NSNull()
139
+ dict["scanTimestamp"] = status.scanTimestamp ?? NSNull()
140
+ dict["scannerId"] = status.scannerId ?? NSNull()
141
+ dict["status"] = status.status ?? NSNull()
142
+
143
+ // metadata
144
+ if let metadata = status.metadata {
145
+ dict["metadata"] = [
146
+ "guid": (metadata.guid as Any?) ?? NSNull(),
147
+ "serverUploadStarted": (metadata.serverUploadStarted as Any?) ?? NSNull()
148
+ ]
149
+ } else {
150
+ dict["metadata"] = NSNull()
151
+ }
152
+
153
+ return dict
154
+ }
155
+
156
+ resolve(mapped)
157
+ },
158
+ onError: { error in
159
+ reject("FETCH_SCAN_STATUSES_FAILED", error.localizedDescription, error)
160
+ }
161
+ )
162
+ }
163
+
164
+ @objc(fetchOnDemandReports:projectId:reportTypes:withResolver:withRejecter:)
165
+ func fetchOnDemandReports(
166
+ scanId: NSNumber,
167
+ projectId: NSNumber?,
168
+ reportTypes: NSArray?,
169
+ resolve: @escaping RCTPromiseResolveBlock,
170
+ reject: @escaping RCTPromiseRejectBlock
171
+ ) {
172
+ func rn(_ value: Any?) -> Any { value ?? NSNull() }
173
+
174
+ let types: [PensaReportType] = {
175
+ guard let arr = reportTypes as? [String], !arr.isEmpty else { return [.itemsSeen] }
176
+ let mapped = arr.compactMap { PensaReportType(rawValue: $0) }
177
+ return mapped.isEmpty ? [.itemsSeen] : mapped
178
+ }()
179
+
180
+ Pensa.shared.fetchOnDemandReports(
181
+ scanId: scanId.intValue,
182
+ projectId: projectId?.intValue,
183
+ reportTypes: types,
184
+ onSuccess: { report in
185
+
186
+ var result: [String: Any] = [
187
+ "shelfId": rn(report.shelfId),
188
+ "shelfName": rn(report.shelfName),
189
+ "status": rn(report.status),
190
+ "projectId": rn(report.projectId),
191
+ "projectName": rn(report.projectName),
192
+ "projectReportId": rn(report.projectReportId),
193
+ "projectReportName": rn(report.projectReportName),
194
+ "realogramSignedUrl": rn(report.realogramSignedUrl)
195
+ ]
196
+
197
+ func addBucket(_ key: String, _ bucket: PensaOnDemandReportBucket?) {
198
+ guard let bucket = bucket else { return } // istenen tip yoksa hiç ekleme
199
+ let products: [[String: Any]] = bucket.productList.map { p in
200
+ [
201
+ "brand": rn(p.brand),
202
+ "brandId": rn(p.brandId),
203
+ "category": rn(p.category),
204
+ "categoryId": rn(p.categoryId),
205
+ "expectedFacings": rn(p.expectedFacings),
206
+ "facings": rn(p.facings),
207
+ "manufacturer": rn(p.manufacturer),
208
+ "manufacturerId": rn(p.manufacturerId),
209
+ "product": rn(p.product),
210
+ "productId": rn(p.productId),
211
+ "upc": rn(p.upc)
212
+ ]
213
+ }
214
+ result[key] = ["productList": products]
215
+ }
216
+
217
+ for t in types {
218
+ switch t {
219
+ case .itemsSeen:
220
+ addBucket("itemsSeen", report.itemsSeen?.report)
221
+ case .facingsSeen:
222
+ addBucket("facingsSeen", report.facingsSeen?.report)
223
+ case .fullFacings:
224
+ addBucket("fullFacings", report.fullFacings?.report)
225
+ case .fullFacingsAndProductPositions:
226
+ addBucket("fullFacingsAndProductPositions", report.fullFacingsAndProductPositions?.report)
227
+ case .newProducts:
228
+ addBucket("newProducts", report.newProducts?.report)
229
+ case .newProductPackaging:
230
+ addBucket("newProductPackaging", report.newProductPackaging?.report)
231
+ case .noOos:
232
+ addBucket("noOos", report.noOos?.report)
233
+ case .oos:
234
+ addBucket("oos", report.oos?.report)
235
+ case .productPositions:
236
+ addBucket("productPositions", report.productPositions?.report)
237
+ case .scanFailed:
238
+ addBucket("scanFailed", report.scanFailed?.report)
239
+ case .scanRejected:
240
+ addBucket("scanRejected", report.scanRejected?.report)
241
+ case .scanSkipped:
242
+ addBucket("scanSkipped", report.scanSkipped?.report)
243
+ }
244
+ }
245
+
246
+ resolve(result)
247
+ },
248
+ onError: { error in
249
+ reject("FETCH_ON_DEMAND_REPORTS_FAILED", error.localizedDescription, error)
250
+ }
251
+ )
252
+ }
253
+
254
+ @objc(fetchProductImageBase64:withResolver:withRejecter:)
255
+ func fetchProductImageBase64(productId: NSNumber,
256
+ resolve: @escaping RCTPromiseResolveBlock,
257
+ reject: @escaping RCTPromiseRejectBlock) {
258
+ Pensa.shared.fetchProductImageBase64(
259
+ productId: productId.intValue,
260
+ onSuccess: { base64 in
261
+ resolve(base64)
262
+ },
263
+ onError: { error in
264
+ reject("FETCH_PRODUCT_IMAGE_BASE64_FAILED", error.localizedDescription, error)
265
+ }
266
+ )
267
+ }
268
+
269
+ @objc(fetchShelves:withResolver:withRejecter:)
270
+ func fetchShelves(globalStoreId: NSString,
271
+ resolve: @escaping RCTPromiseResolveBlock,
272
+ reject: @escaping RCTPromiseRejectBlock) {
273
+ Pensa.shared.fetchShelves(
274
+ globalStoreId: globalStoreId as String,
275
+ onSuccess: { shelves in
276
+ let mapped: [[String: Any]] = shelves.map { shelf in
277
+ [
278
+ "id": shelf.id,
279
+ "name": shelf.name ?? NSNull()
280
+ ]
281
+ }
282
+
283
+ resolve(mapped)
284
+ },
285
+ onError: { error in
286
+ reject("FETCH_SHELVES_FAILED", error.localizedDescription, error)
287
+ }
288
+ )
289
+ }
121
290
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import { NativeModules, Platform } from 'react-native';
4
+ import { PensaReportType } from "./types.js";
4
5
  const LINKING_ERROR = `The package 'pensa-sdk-react-native' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
5
6
  ios: "- You have run 'pod install'\n",
6
7
  default: ''
@@ -37,6 +38,20 @@ export const showStockingScreen = () => {
37
38
  export const showStoreChecklist = (globalStoreId, guid, sectionKey) => {
38
39
  return PensaSdkReactNative.showStoreChecklist(globalStoreId, guid, sectionKey);
39
40
  };
41
+ export const fetchScanStatuses = scanIds => {
42
+ return PensaSdkReactNative.fetchScanStatuses(scanIds);
43
+ };
44
+ export const fetchOnDemandReports = (scanId, projectId, reportTypes) => {
45
+ const finalReportTypes = reportTypes && reportTypes.length > 0 ? reportTypes : [PensaReportType.ITEMS_SEEN];
46
+ return PensaSdkReactNative.fetchOnDemandReports(scanId, projectId ?? null, finalReportTypes);
47
+ };
48
+ export const fetchProductImageBase64 = productId => {
49
+ return PensaSdkReactNative.fetchProductImageBase64(productId);
50
+ };
51
+ export const fetchShelves = globalStoreId => {
52
+ return PensaSdkReactNative.fetchShelves(globalStoreId);
53
+ };
40
54
  export * from "./events.js";
41
55
  export * from "./types.js";
56
+ export { PensaReportType } from "./types.js";
42
57
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","PensaSdkReactNative","Proxy","get","Error","initPensa","config","isPensaStarted","showShelfScans","showProductScans","showStoreSearchView","showStoresScreen","showScanArea","scanId","storeId","globalStoreId","showStockingScreen","showStoreChecklist","guid","sectionKey"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,iFAAiF,GACjFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,mBAAmB,GAAGN,aAAa,CAACM,mBAAmB,GACzDN,aAAa,CAACM,mBAAmB,GACjC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,OAAO,MAAMQ,SAAS,GAAIC,MAIzB,IAAoB;EACnB,OAAOL,mBAAmB,CAACI,SAAS,CAACC,MAAM,CAAC;AAC9C,CAAC;AAED,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAwB;EACpD,OAAON,mBAAmB,CAACM,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAqB;EACjD,OAAOP,mBAAmB,CAACO,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,OAAO,MAAMC,gBAAgB,GAAGA,CAAA,KAAqB;EACnD,OAAOR,mBAAmB,CAACQ,gBAAgB,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,MAAMC,mBAAmB,GAAGA,CAAA,KAAqB;EACtD,OAAOT,mBAAmB,CAACS,mBAAmB,CAAC,CAAC;AAClD,CAAC;AAED,OAAO,MAAMC,gBAAgB,GAAGA,CAAA,KAAqB;EACnD,OAAOV,mBAAmB,CAACU,gBAAgB,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,MAAMC,YAAY,GAAGA,CAC1BC,MAAc,EACdC,OAAgB,EAChBC,aAAsB,KACJ;EAClB,OAAOd,mBAAmB,CAACW,YAAY,CACrCC,MAAM,EACNC,OAAO,IAAI,IAAI,EACfC,aAAa,IAAI,IACnB,CAAC;AACH,CAAC;AAED,OAAO,MAAMC,kBAAkB,GAAGA,CAAA,KAAqB;EACrD,OAAOf,mBAAmB,CAACe,kBAAkB,CAAC,CAAC;AACjD,CAAC;AAED,OAAO,MAAMC,kBAAkB,GAAGA,CAChCF,aAAqB,EACrBG,IAAa,EACbC,UAAmB,KACD;EAClB,OAAOlB,mBAAmB,CAACgB,kBAAkB,CAC3CF,aAAa,EACbG,IAAI,EACJC,UACF,CAAC;AACH,CAAC;AAED,cAAc,aAAU;AACxB,cAAc,YAAS","ignoreList":[]}
1
+ {"version":3,"names":["NativeModules","Platform","PensaReportType","LINKING_ERROR","select","ios","default","PensaSdkReactNative","Proxy","get","Error","initPensa","config","isPensaStarted","showShelfScans","showProductScans","showStoreSearchView","showStoresScreen","showScanArea","scanId","storeId","globalStoreId","showStockingScreen","showStoreChecklist","guid","sectionKey","fetchScanStatuses","scanIds","fetchOnDemandReports","projectId","reportTypes","finalReportTypes","length","ITEMS_SEEN","fetchProductImageBase64","productId","fetchShelves"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAMtD,SAASC,eAAe,QAAQ,YAAS;AAEzC,MAAMC,aAAa,GACjB,iFAAiF,GACjFF,QAAQ,CAACG,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,mBAAmB,GAAGP,aAAa,CAACO,mBAAmB,GACzDP,aAAa,CAACO,mBAAmB,GACjC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,OAAO,MAAMQ,SAAS,GAAIC,MAIzB,IAAoB;EACnB,OAAOL,mBAAmB,CAACI,SAAS,CAACC,MAAM,CAAC;AAC9C,CAAC;AAED,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAwB;EACpD,OAAON,mBAAmB,CAACM,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAqB;EACjD,OAAOP,mBAAmB,CAACO,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,OAAO,MAAMC,gBAAgB,GAAGA,CAAA,KAAqB;EACnD,OAAOR,mBAAmB,CAACQ,gBAAgB,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,MAAMC,mBAAmB,GAAGA,CAAA,KAAqB;EACtD,OAAOT,mBAAmB,CAACS,mBAAmB,CAAC,CAAC;AAClD,CAAC;AAED,OAAO,MAAMC,gBAAgB,GAAGA,CAAA,KAAqB;EACnD,OAAOV,mBAAmB,CAACU,gBAAgB,CAAC,CAAC;AAC/C,CAAC;AAED,OAAO,MAAMC,YAAY,GAAGA,CAC1BC,MAAc,EACdC,OAAgB,EAChBC,aAAsB,KACJ;EAClB,OAAOd,mBAAmB,CAACW,YAAY,CACrCC,MAAM,EACNC,OAAO,IAAI,IAAI,EACfC,aAAa,IAAI,IACnB,CAAC;AACH,CAAC;AAED,OAAO,MAAMC,kBAAkB,GAAGA,CAAA,KAAqB;EACrD,OAAOf,mBAAmB,CAACe,kBAAkB,CAAC,CAAC;AACjD,CAAC;AAED,OAAO,MAAMC,kBAAkB,GAAGA,CAChCF,aAAqB,EACrBG,IAAa,EACbC,UAAmB,KACD;EAClB,OAAOlB,mBAAmB,CAACgB,kBAAkB,CAC3CF,aAAa,EACbG,IAAI,EACJC,UACF,CAAC;AACH,CAAC;AAED,OAAO,MAAMC,iBAAiB,GAC5BC,OAAiB,IACc;EAC/B,OAAOpB,mBAAmB,CAACmB,iBAAiB,CAACC,OAAO,CAAC;AACvD,CAAC;AAED,OAAO,MAAMC,oBAAoB,GAAGA,CAClCT,MAAc,EACdU,SAAkB,EAClBC,WAA+B,KACE;EACjC,MAAMC,gBAAgB,GACpBD,WAAW,IAAIA,WAAW,CAACE,MAAM,GAAG,CAAC,GACjCF,WAAW,GACX,CAAC5B,eAAe,CAAC+B,UAAU,CAAC;EAElC,OAAO1B,mBAAmB,CAACqB,oBAAoB,CAC7CT,MAAM,EACNU,SAAS,IAAI,IAAI,EACjBE,gBACF,CAAC;AACH,CAAC;AAED,OAAO,MAAMG,uBAAuB,GAAIC,SAAiB,IAAsB;EAC7E,OAAO5B,mBAAmB,CAAC2B,uBAAuB,CAACC,SAAS,CAAC;AAC/D,CAAC;AAED,OAAO,MAAMC,YAAY,GACvBf,aAAqB,IACS;EAC9B,OAAOd,mBAAmB,CAAC6B,YAAY,CAACf,aAAa,CAAC;AACxD,CAAC;AAED,cAAc,aAAU;AACxB,cAAc,YAAS;AACvB,SAASnB,eAAe,QAAQ,YAAS","ignoreList":[]}
@@ -1,2 +1,18 @@
1
1
  "use strict";
2
+
3
+ export let PensaReportType = /*#__PURE__*/function (PensaReportType) {
4
+ PensaReportType["FACINGS_SEEN"] = "FACINGS_SEEN";
5
+ PensaReportType["FULL_FACINGS"] = "FULL_FACINGS";
6
+ PensaReportType["FULL_FACINGS_AND_PRODUCT_POSITIONS"] = "FULL_FACINGS_AND_PRODUCT_POSITIONS";
7
+ PensaReportType["ITEMS_SEEN"] = "ITEMS_SEEN";
8
+ PensaReportType["NEW_PRODUCTS"] = "NEW_PRODUCTS";
9
+ PensaReportType["NEW_PRODUCT_PACKAGING"] = "NEW_PRODUCT_PACKAGING";
10
+ PensaReportType["NO_OOS"] = "NO_OOS";
11
+ PensaReportType["OOS"] = "OOS";
12
+ PensaReportType["PRODUCT_POSITIONS"] = "PRODUCT_POSITIONS";
13
+ PensaReportType["SCAN_FAILED"] = "SCAN_FAILED";
14
+ PensaReportType["SCAN_REJECTED"] = "SCAN_REJECTED";
15
+ PensaReportType["SCAN_SKIPPED"] = "SCAN_SKIPPED";
16
+ return PensaReportType;
17
+ }({});
2
18
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":["PensaReportType"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;AAsFA,WAAYA,eAAe,0BAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAfA,eAAe;EAAA,OAAfA,eAAe;AAAA","ignoreList":[]}
@@ -1,3 +1,5 @@
1
+ import type { PensaOnDemandReport, PensaScanStatus, PensaShelfItem } from './types';
2
+ import { PensaReportType } from './types';
1
3
  export declare const initPensa: (config: {
2
4
  clientId: string;
3
5
  clientSecret: string;
@@ -11,6 +13,11 @@ export declare const showStoresScreen: () => Promise<void>;
11
13
  export declare const showScanArea: (scanId: number, storeId?: number, globalStoreId?: string) => Promise<void>;
12
14
  export declare const showStockingScreen: () => Promise<void>;
13
15
  export declare const showStoreChecklist: (globalStoreId: string, guid?: string, sectionKey?: string) => Promise<void>;
16
+ export declare const fetchScanStatuses: (scanIds: number[]) => Promise<PensaScanStatus[]>;
17
+ export declare const fetchOnDemandReports: (scanId: number, projectId?: number, reportTypes?: PensaReportType[]) => Promise<PensaOnDemandReport>;
18
+ export declare const fetchProductImageBase64: (productId: number) => Promise<string>;
19
+ export declare const fetchShelves: (globalStoreId: string) => Promise<PensaShelfItem[]>;
14
20
  export * from './events';
15
21
  export * from './types';
22
+ export { PensaReportType } from './types';
16
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAmBA,eAAO,MAAM,SAAS,GAAI,QAAQ;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,KAAG,OAAO,CAAC,IAAI,CAEf,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAAO,CAAC,OAAO,CAEhD,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAAO,CAAC,IAAI,CAE7C,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,OAAO,CAAC,IAAI,CAE/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,OAAO,CAAC,IAAI,CAElD,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,OAAO,CAAC,IAAI,CAE/C,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,EACd,UAAU,MAAM,EAChB,gBAAgB,MAAM,KACrB,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,OAAO,CAAC,IAAI,CAEjD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,eAAe,MAAM,EACrB,OAAO,MAAM,EACb,aAAa,MAAM,KAClB,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,cAAc,EACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAmB1C,eAAO,MAAM,SAAS,GAAI,QAAQ;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,KAAG,OAAO,CAAC,IAAI,CAEf,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAAO,CAAC,OAAO,CAEhD,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAAO,CAAC,IAAI,CAE7C,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,OAAO,CAAC,IAAI,CAE/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,OAAO,CAAC,IAAI,CAElD,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,OAAO,CAAC,IAAI,CAE/C,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,EACd,UAAU,MAAM,EAChB,gBAAgB,MAAM,KACrB,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,OAAO,CAAC,IAAI,CAEjD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,eAAe,MAAM,EACrB,OAAO,MAAM,EACb,aAAa,MAAM,KAClB,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EAAE,KAChB,OAAO,CAAC,eAAe,EAAE,CAE3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,YAAY,MAAM,EAClB,cAAc,eAAe,EAAE,KAC9B,OAAO,CAAC,mBAAmB,CAW7B,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,WAAW,MAAM,KAAG,OAAO,CAAC,MAAM,CAEzE,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,eAAe,MAAM,KACpB,OAAO,CAAC,cAAc,EAAE,CAE1B,CAAC;AAEF,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
@@ -23,4 +23,73 @@ export type PensaEventPayloads = {
23
23
  onScanUploadFailed: OnScanUploadFailed;
24
24
  onCantScanReported: OnCantScanReported;
25
25
  };
26
+ export type PensaScanMetadata = {
27
+ guid: string | null;
28
+ serverUploadStarted: string | null;
29
+ };
30
+ export type PensaScanStatus = {
31
+ created: string | null;
32
+ fastStatus: string | null;
33
+ id: number;
34
+ metadata: PensaScanMetadata | null;
35
+ scanTimestamp: string | null;
36
+ scannerId: string | null;
37
+ status: string | null;
38
+ };
39
+ export type PensaOnDemandProduct = {
40
+ brand: string | null;
41
+ brandId: number | null;
42
+ category: string | null;
43
+ categoryId: number | null;
44
+ expectedFacings: number | null;
45
+ facings: number | null;
46
+ manufacturer: string | null;
47
+ manufacturerId: number | null;
48
+ product: string | null;
49
+ productId: number | null;
50
+ upc: string | null;
51
+ };
52
+ export type PensaOnDemandReportBucket = {
53
+ productList: PensaOnDemandProduct[];
54
+ };
55
+ export type PensaOnDemandReport = {
56
+ facingsSeen: PensaOnDemandReportBucket | null;
57
+ fullFacings: PensaOnDemandReportBucket | null;
58
+ fullFacingsAndProductPositions: PensaOnDemandReportBucket | null;
59
+ itemsSeen: PensaOnDemandReportBucket | null;
60
+ newProducts: PensaOnDemandReportBucket | null;
61
+ newProductPackaging: PensaOnDemandReportBucket | null;
62
+ noOos: PensaOnDemandReportBucket | null;
63
+ oos: PensaOnDemandReportBucket | null;
64
+ productPositions: PensaOnDemandReportBucket | null;
65
+ scanFailed: PensaOnDemandReportBucket | null;
66
+ scanRejected: PensaOnDemandReportBucket | null;
67
+ scanSkipped: PensaOnDemandReportBucket | null;
68
+ projectId: number | null;
69
+ projectName: string | null;
70
+ projectReportId: number | null;
71
+ projectReportName: string | null;
72
+ realogramSignedUrl: string | null;
73
+ shelfId: number | null;
74
+ shelfName: string | null;
75
+ status: string | null;
76
+ };
77
+ export declare enum PensaReportType {
78
+ FACINGS_SEEN = "FACINGS_SEEN",
79
+ FULL_FACINGS = "FULL_FACINGS",
80
+ FULL_FACINGS_AND_PRODUCT_POSITIONS = "FULL_FACINGS_AND_PRODUCT_POSITIONS",
81
+ ITEMS_SEEN = "ITEMS_SEEN",
82
+ NEW_PRODUCTS = "NEW_PRODUCTS",
83
+ NEW_PRODUCT_PACKAGING = "NEW_PRODUCT_PACKAGING",
84
+ NO_OOS = "NO_OOS",
85
+ OOS = "OOS",
86
+ PRODUCT_POSITIONS = "PRODUCT_POSITIONS",
87
+ SCAN_FAILED = "SCAN_FAILED",
88
+ SCAN_REJECTED = "SCAN_REJECTED",
89
+ SCAN_SKIPPED = "SCAN_SKIPPED"
90
+ }
91
+ export type PensaShelfItem = {
92
+ id: number;
93
+ name: string | null;
94
+ };
26
95
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,0BAA0B,EAAE,0BAA0B,CAAC;IACvD,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,kBAAkB,EAAE,kBAAkB,CAAC;CACxC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,0BAA0B,EAAE,0BAA0B,CAAC;IACvD,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,kBAAkB,EAAE,kBAAkB,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC9C,WAAW,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC9C,8BAA8B,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACjE,SAAS,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5C,WAAW,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC9C,mBAAmB,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACtD,KAAK,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACxC,GAAG,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACtC,gBAAgB,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACnD,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC7C,YAAY,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC/C,WAAW,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC9C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,oBAAY,eAAe;IACzB,YAAY,iBAAiB;IAC7B,YAAY,iBAAiB;IAC7B,kCAAkC,uCAAuC;IACzE,UAAU,eAAe;IACzB,YAAY,iBAAiB;IAC7B,qBAAqB,0BAA0B;IAC/C,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,iBAAiB,sBAAsB;IACvC,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,YAAY,iBAAiB;CAC9B;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pensasystems/pensa-react-native",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0",
4
4
  "description": "The Pensa Mobile App SDK is a developer toolkit designed to simplify adding Pensa’s capabilities to your mobile applications. It provides pre-built libraries, tools, and APIs to accelerate development and integration, offering streamlined SDK integration, easy initialization, and comprehensive functionality. With the Pensa SDK, you can enhance your app’s features or seamlessly integrate with other services for a cohesive user experience.",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
@@ -68,7 +68,6 @@
68
68
  "@release-it/conventional-changelog": "^9.0.2",
69
69
  "@types/jest": "^29.5.5",
70
70
  "@types/react": "^19.0.0",
71
- "commitlint": "^19.6.1",
72
71
  "del-cli": "^5.1.0",
73
72
  "eslint": "^9.22.0",
74
73
  "eslint-config-prettier": "^10.1.1",
package/src/index.tsx CHANGED
@@ -1,4 +1,10 @@
1
1
  import { NativeModules, Platform } from 'react-native';
2
+ import type {
3
+ PensaOnDemandReport,
4
+ PensaScanStatus,
5
+ PensaShelfItem,
6
+ } from './types';
7
+ import { PensaReportType } from './types';
2
8
 
3
9
  const LINKING_ERROR =
4
10
  `The package 'pensa-sdk-react-native' doesn't seem to be linked. Make sure: \n\n` +
@@ -73,5 +79,39 @@ export const showStoreChecklist = (
73
79
  );
74
80
  };
75
81
 
82
+ export const fetchScanStatuses = (
83
+ scanIds: number[]
84
+ ): Promise<PensaScanStatus[]> => {
85
+ return PensaSdkReactNative.fetchScanStatuses(scanIds);
86
+ };
87
+
88
+ export const fetchOnDemandReports = (
89
+ scanId: number,
90
+ projectId?: number,
91
+ reportTypes?: PensaReportType[]
92
+ ): Promise<PensaOnDemandReport> => {
93
+ const finalReportTypes =
94
+ reportTypes && reportTypes.length > 0
95
+ ? reportTypes
96
+ : [PensaReportType.ITEMS_SEEN];
97
+
98
+ return PensaSdkReactNative.fetchOnDemandReports(
99
+ scanId,
100
+ projectId ?? null,
101
+ finalReportTypes
102
+ );
103
+ };
104
+
105
+ export const fetchProductImageBase64 = (productId: number): Promise<string> => {
106
+ return PensaSdkReactNative.fetchProductImageBase64(productId);
107
+ };
108
+
109
+ export const fetchShelves = (
110
+ globalStoreId: string
111
+ ): Promise<PensaShelfItem[]> => {
112
+ return PensaSdkReactNative.fetchShelves(globalStoreId);
113
+ };
114
+
76
115
  export * from './events';
77
116
  export * from './types';
117
+ export { PensaReportType } from './types';
package/src/types.ts CHANGED
@@ -27,3 +27,79 @@ export type PensaEventPayloads = {
27
27
  onScanUploadFailed: OnScanUploadFailed;
28
28
  onCantScanReported: OnCantScanReported;
29
29
  };
30
+
31
+ export type PensaScanMetadata = {
32
+ guid: string | null;
33
+ serverUploadStarted: string | null;
34
+ };
35
+
36
+ export type PensaScanStatus = {
37
+ created: string | null;
38
+ fastStatus: string | null;
39
+ id: number;
40
+ metadata: PensaScanMetadata | null;
41
+ scanTimestamp: string | null;
42
+ scannerId: string | null;
43
+ status: string | null;
44
+ };
45
+
46
+ export type PensaOnDemandProduct = {
47
+ brand: string | null;
48
+ brandId: number | null;
49
+ category: string | null;
50
+ categoryId: number | null;
51
+ expectedFacings: number | null;
52
+ facings: number | null;
53
+ manufacturer: string | null;
54
+ manufacturerId: number | null;
55
+ product: string | null;
56
+ productId: number | null;
57
+ upc: string | null;
58
+ };
59
+
60
+ export type PensaOnDemandReportBucket = {
61
+ productList: PensaOnDemandProduct[];
62
+ };
63
+
64
+ export type PensaOnDemandReport = {
65
+ facingsSeen: PensaOnDemandReportBucket | null;
66
+ fullFacings: PensaOnDemandReportBucket | null;
67
+ fullFacingsAndProductPositions: PensaOnDemandReportBucket | null;
68
+ itemsSeen: PensaOnDemandReportBucket | null;
69
+ newProducts: PensaOnDemandReportBucket | null;
70
+ newProductPackaging: PensaOnDemandReportBucket | null;
71
+ noOos: PensaOnDemandReportBucket | null;
72
+ oos: PensaOnDemandReportBucket | null;
73
+ productPositions: PensaOnDemandReportBucket | null;
74
+ scanFailed: PensaOnDemandReportBucket | null;
75
+ scanRejected: PensaOnDemandReportBucket | null;
76
+ scanSkipped: PensaOnDemandReportBucket | null;
77
+ projectId: number | null;
78
+ projectName: string | null;
79
+ projectReportId: number | null;
80
+ projectReportName: string | null;
81
+ realogramSignedUrl: string | null;
82
+ shelfId: number | null;
83
+ shelfName: string | null;
84
+ status: string | null;
85
+ };
86
+
87
+ export enum PensaReportType {
88
+ FACINGS_SEEN = 'FACINGS_SEEN',
89
+ FULL_FACINGS = 'FULL_FACINGS',
90
+ FULL_FACINGS_AND_PRODUCT_POSITIONS = 'FULL_FACINGS_AND_PRODUCT_POSITIONS',
91
+ ITEMS_SEEN = 'ITEMS_SEEN',
92
+ NEW_PRODUCTS = 'NEW_PRODUCTS',
93
+ NEW_PRODUCT_PACKAGING = 'NEW_PRODUCT_PACKAGING',
94
+ NO_OOS = 'NO_OOS',
95
+ OOS = 'OOS',
96
+ PRODUCT_POSITIONS = 'PRODUCT_POSITIONS',
97
+ SCAN_FAILED = 'SCAN_FAILED',
98
+ SCAN_REJECTED = 'SCAN_REJECTED',
99
+ SCAN_SKIPPED = 'SCAN_SKIPPED',
100
+ }
101
+
102
+ export type PensaShelfItem = {
103
+ id: number;
104
+ name: string | null;
105
+ };