@passgage/sdk-react-native 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,75 +1,91 @@
1
- "use strict";
2
- var __create = Object.create;
1
+ 'use strict';
2
+
3
+ var axios = require('axios');
4
+ var React = require('react');
5
+ var zustand = require('zustand');
6
+ var Keychain = require('react-native-keychain');
7
+ var Geolocation2 = require('react-native-geolocation-service');
8
+ var RNPermissions = require('react-native-permissions');
9
+ var reactNative = require('react-native');
10
+ var NfcManager = require('react-native-nfc-manager');
11
+
12
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
+
14
+ function _interopNamespace(e) {
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n.default = e;
29
+ return Object.freeze(n);
30
+ }
31
+
32
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
33
+ var React__default = /*#__PURE__*/_interopDefault(React);
34
+ var Keychain__namespace = /*#__PURE__*/_interopNamespace(Keychain);
35
+ var Geolocation2__default = /*#__PURE__*/_interopDefault(Geolocation2);
36
+ var RNPermissions__default = /*#__PURE__*/_interopDefault(RNPermissions);
37
+ var NfcManager__default = /*#__PURE__*/_interopDefault(NfcManager);
38
+
3
39
  var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
40
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
41
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
42
+ }) : x)(function(x) {
43
+ if (typeof require !== "undefined") return require.apply(this, arguments);
44
+ throw Error('Dynamic require of "' + x + '" is not supported');
45
+ });
8
46
  var __export = (target, all) => {
9
47
  for (var name in all)
10
48
  __defProp(target, name, { get: all[name], enumerable: true });
11
49
  };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
50
+ var httpClient = axios__default.default.create();
51
+ var createHttpClient = ({
52
+ baseURL,
53
+ apiVersion,
54
+ timeout = 3e3
55
+ }) => {
56
+ httpClient = axios__default.default.create({
57
+ baseURL: `${baseURL}/api/${apiVersion}`,
58
+ timeout,
59
+ headers: {
60
+ "Content-Type": "application/json",
61
+ Accept: "application/json"
62
+ }
63
+ });
64
+ httpClient.interceptors.request.use(
65
+ (config) => {
66
+ return config;
67
+ },
68
+ (error) => {
69
+ return Promise.reject(error);
70
+ }
71
+ );
72
+ httpClient.interceptors.response.use(
73
+ (response) => {
74
+ const originalRequest = response.config;
75
+ if (response.status === 401 && originalRequest) {
76
+ return new Promise(async (resolve, _reject) => {
77
+ });
78
+ }
79
+ return response.data;
80
+ },
81
+ (err) => {
82
+ return Promise.reject(err);
83
+ }
84
+ );
85
+ };
86
+ var setTokenToHttpClient = (token) => {
87
+ httpClient.defaults.headers["Authorization"] = token ? `Bearer ${token}` : "";
19
88
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- ApiClient: () => ApiClient,
34
- AuthService: () => AuthService,
35
- CheckInService: () => CheckInService,
36
- DeviceAccessService: () => DeviceAccessService,
37
- DeviceDirection: () => DeviceDirection,
38
- DeviceUsage: () => DeviceUsage,
39
- Endpoints: () => endpoints_exports,
40
- EntranceType: () => EntranceType,
41
- LocationService: () => LocationService,
42
- NFCAccessService: () => NFCAccessService,
43
- PassgageAccessProvider: () => PassgageAccessProvider,
44
- QRAccessService: () => QRAccessService,
45
- RemoteWorkService: () => RemoteWorkService,
46
- SDK_VERSION: () => SDK_VERSION,
47
- calculateDistance: () => calculateDistance,
48
- checkOnLocation: () => checkOnLocation,
49
- checkRepetitiveRead: () => checkRepetitiveRead,
50
- clearReadRecords: () => clearReadRecords,
51
- createApiClient: () => createApiClient,
52
- formatDate: () => formatDate,
53
- formatDateTime: () => formatDateTime,
54
- formatISO: () => formatISO,
55
- formatTime: () => formatTime,
56
- parseISO: () => parseISO,
57
- useLocation: () => useLocation,
58
- usePassgageAccess: () => usePassgageAccess,
59
- usePassgageAuth: () => usePassgageAuth,
60
- usePassgageCheckIn: () => usePassgageCheckIn,
61
- usePassgageNFCScanner: () => usePassgageNFCScanner,
62
- usePassgageQRScanner: () => usePassgageQRScanner,
63
- usePassgageRemoteWork: () => usePassgageRemoteWork,
64
- validateCoordinates: () => validateCoordinates,
65
- validateDeviceId: () => validateDeviceId,
66
- validateNFCCode: () => validateNFCCode,
67
- validateQRCode: () => validateQRCode
68
- });
69
- module.exports = __toCommonJS(index_exports);
70
-
71
- // src/api/client.ts
72
- var import_axios = __toESM(require("axios"));
73
89
  var ApiClient = class {
74
90
  constructor(config) {
75
91
  this.isRefreshing = false;
@@ -79,7 +95,7 @@ var ApiClient = class {
79
95
  apiVersion: "v2",
80
96
  ...config
81
97
  };
82
- this.axiosInstance = import_axios.default.create({
98
+ this.axiosInstance = axios__default.default.create({
83
99
  baseURL: `${this.config.baseURL}/api/${this.config.apiVersion}`,
84
100
  timeout: this.config.timeout,
85
101
  headers: {
@@ -230,32 +246,24 @@ var ApiClient = class {
230
246
  * Generic PUT request
231
247
  */
232
248
  async put(options) {
233
- const response = await this.axiosInstance.put(
234
- options.endpoint,
235
- options.data,
236
- {
237
- params: options.params,
238
- headers: options.headers,
239
- ...options.config,
240
- skipAuth: options.skipAuth
241
- }
242
- );
249
+ const response = await this.axiosInstance.put(options.endpoint, options.data, {
250
+ params: options.params,
251
+ headers: options.headers,
252
+ ...options.config,
253
+ skipAuth: options.skipAuth
254
+ });
243
255
  return response.data;
244
256
  }
245
257
  /**
246
258
  * Generic PATCH request
247
259
  */
248
260
  async patch(options) {
249
- const response = await this.axiosInstance.patch(
250
- options.endpoint,
251
- options.data,
252
- {
253
- params: options.params,
254
- headers: options.headers,
255
- ...options.config,
256
- skipAuth: options.skipAuth
257
- }
258
- );
261
+ const response = await this.axiosInstance.patch(options.endpoint, options.data, {
262
+ params: options.params,
263
+ headers: options.headers,
264
+ ...options.config,
265
+ skipAuth: options.skipAuth
266
+ });
259
267
  return response.data;
260
268
  }
261
269
  /**
@@ -278,6 +286,7 @@ function createApiClient(config) {
278
286
  // src/api/endpoints.ts
279
287
  var endpoints_exports = {};
280
288
  __export(endpoints_exports, {
289
+ EP_AZURE_AUTH: () => EP_AZURE_AUTH,
281
290
  EP_BRANCHES: () => EP_BRANCHES,
282
291
  EP_CREATE_QR: () => EP_CREATE_QR,
283
292
  EP_DEVICES: () => EP_DEVICES,
@@ -295,6 +304,7 @@ __export(endpoints_exports, {
295
304
  });
296
305
  var EP_LOGIN = "users/sign_in";
297
306
  var EP_TOKEN = "token";
307
+ var EP_AZURE_AUTH = "auth/azure";
298
308
  var EP_DEVICES = "devices";
299
309
  var EP_QR_DEVICES = "devices/qr_devices";
300
310
  var EP_QR_ACCESS = "qr_access/accessible_qrs";
@@ -328,17 +338,7 @@ var DeviceDirection = /* @__PURE__ */ ((DeviceDirection2) => {
328
338
  })(DeviceDirection || {});
329
339
 
330
340
  // src/services/AuthService.ts
331
- var AuthService = class {
332
- constructor(apiClient) {
333
- this.apiClient = apiClient;
334
- }
335
- /**
336
- * Set token storage implementation
337
- * This is used by platform-specific implementations (React Native, Android, iOS)
338
- */
339
- setTokenStorage(storage) {
340
- this.tokenStorage = storage;
341
- }
341
+ var AuthService = {
342
342
  /**
343
343
  * Login with credentials
344
344
  *
@@ -359,7 +359,7 @@ var AuthService = class {
359
359
  * }
360
360
  * ```
361
361
  */
362
- async login(credentials) {
362
+ login: async (credentials) => {
363
363
  try {
364
364
  const requestBody = {
365
365
  user: {
@@ -367,12 +367,7 @@ var AuthService = class {
367
367
  password: credentials.password
368
368
  }
369
369
  };
370
- const response = await this.apiClient.post({
371
- endpoint: "/api/v2/users/sign_in",
372
- data: requestBody,
373
- skipAuth: true
374
- // Don't send auth header for login
375
- });
370
+ const response = await httpClient.post(EP_LOGIN, requestBody);
376
371
  if (!response.success || !response.data?.tokens) {
377
372
  return {
378
373
  success: false,
@@ -381,18 +376,12 @@ var AuthService = class {
381
376
  };
382
377
  }
383
378
  const tokens = response.data.tokens;
384
- if (this.tokenStorage) {
385
- await this.tokenStorage.saveTokens(tokens);
386
- }
387
- this.apiClient.setToken(tokens.access.token);
379
+ setTokenToHttpClient(tokens.access.token);
388
380
  let user;
389
381
  try {
390
- const userResult = await this.getCurrentUser();
382
+ const userResult = await AuthService.getCurrentUser();
391
383
  if (userResult.success) {
392
384
  user = userResult.user;
393
- if (this.tokenStorage) {
394
- await this.tokenStorage.saveUser(user);
395
- }
396
385
  }
397
386
  } catch (error) {
398
387
  console.warn("Failed to fetch user info after login:", error);
@@ -409,7 +398,68 @@ var AuthService = class {
409
398
  code: error.code || "NETWORK_ERROR"
410
399
  };
411
400
  }
412
- }
401
+ },
402
+ /**
403
+ * Login with Azure AD token
404
+ *
405
+ * @param credentials - Azure AD login credentials (id_token and optional device_type)
406
+ * @returns Login result with tokens on success
407
+ *
408
+ * @example
409
+ * ```typescript
410
+ * const result = await authService.loginWithAzure({
411
+ * id_token: 'azure_id_token_here',
412
+ * device_type: 'ios'
413
+ * });
414
+ *
415
+ * if (result.success) {
416
+ * console.log('Access token:', result.tokens.access.token);
417
+ * } else {
418
+ * console.error('Azure login failed:', result.error);
419
+ * }
420
+ * ```
421
+ */
422
+ loginWithAzure: async (credentials) => {
423
+ try {
424
+ const response = await httpClient.post(
425
+ EP_AZURE_AUTH,
426
+ {
427
+ id_token: credentials.id_token,
428
+ device_type: credentials.device_type || "android"
429
+ },
430
+ { skipAuth: true }
431
+ );
432
+ if (!response.success || !response.data?.tokens) {
433
+ return {
434
+ success: false,
435
+ error: response.message || "Azure login failed",
436
+ code: "AZURE_LOGIN_FAILED"
437
+ };
438
+ }
439
+ const tokens = response.data.tokens;
440
+ setTokenToHttpClient(tokens.access.token);
441
+ let user;
442
+ try {
443
+ const userResult = await AuthService.getCurrentUser();
444
+ if (userResult.success) {
445
+ user = userResult.user;
446
+ }
447
+ } catch (error) {
448
+ console.warn("Failed to fetch user info after Azure login:", error);
449
+ }
450
+ return {
451
+ success: true,
452
+ tokens,
453
+ user
454
+ };
455
+ } catch (error) {
456
+ return {
457
+ success: false,
458
+ error: error.message || "An error occurred during Azure login",
459
+ code: error.code || "NETWORK_ERROR"
460
+ };
461
+ }
462
+ },
413
463
  /**
414
464
  * Refresh access token using refresh token
415
465
  *
@@ -425,16 +475,18 @@ var AuthService = class {
425
475
  * }
426
476
  * ```
427
477
  */
428
- async refreshToken(refreshToken) {
478
+ refreshToken: async (refreshToken) => {
429
479
  try {
430
480
  const requestBody = {
431
481
  refresh_token: refreshToken
432
482
  };
433
- const response = await this.apiClient.post({
434
- endpoint: "/token",
435
- data: requestBody,
436
- skipAuth: true
437
- });
483
+ const response = await httpClient.post(
484
+ "/token",
485
+ {
486
+ data: requestBody
487
+ },
488
+ { skipAuth: true }
489
+ );
438
490
  if (!response.success || !response.data?.token || !response.data?.refresh_token) {
439
491
  return {
440
492
  success: false,
@@ -444,18 +496,14 @@ var AuthService = class {
444
496
  }
445
497
  const tokens = {
446
498
  access: {
447
- token: response.data.token,
499
+ token: response.data.token ?? "",
448
500
  expiresIn: "30 days"
449
501
  },
450
502
  refresh: {
451
- token: response.data.refresh_token,
503
+ token: response.data.refresh_token ?? "",
452
504
  expiresIn: "30 days"
453
505
  }
454
506
  };
455
- if (this.tokenStorage) {
456
- await this.tokenStorage.saveTokens(tokens);
457
- }
458
- this.apiClient.setToken(tokens.access.token);
459
507
  return {
460
508
  success: true,
461
509
  tokens
@@ -467,7 +515,7 @@ var AuthService = class {
467
515
  code: error.code || "NETWORK_ERROR"
468
516
  };
469
517
  }
470
- }
518
+ },
471
519
  /**
472
520
  * Get current user information
473
521
  *
@@ -482,12 +530,10 @@ var AuthService = class {
482
530
  * }
483
531
  * ```
484
532
  */
485
- async getCurrentUser() {
533
+ getCurrentUser: async () => {
486
534
  try {
487
- const response = await this.apiClient.get({
488
- endpoint: "/api/v2/users/me"
489
- });
490
- if (!response.success || !response.data) {
535
+ const response = await httpClient.get(EP_ME);
536
+ if (!response || !response.data) {
491
537
  return {
492
538
  success: false,
493
539
  error: response.message || "Failed to fetch user information"
@@ -521,69 +567,40 @@ var AuthService = class {
521
567
  };
522
568
  }
523
569
  }
570
+ };
571
+
572
+ // src/services/QRAccessService.ts
573
+ var QRAccessService = {
524
574
  /**
525
- * Logout current user
526
- * Clears tokens from storage and API client
527
- *
528
- * @example
529
- * ```typescript
530
- * await authService.logout();
531
- * console.log('User logged out');
532
- * ```
533
- */
534
- async logout() {
535
- if (this.tokenStorage) {
536
- await this.tokenStorage.clearTokens();
537
- await this.tokenStorage.clearUser();
538
- }
539
- this.apiClient.setToken(null);
540
- }
541
- /**
542
- * Check if user is authenticated
543
- *
544
- * @returns True if user has valid tokens
545
- */
546
- async isAuthenticated() {
547
- if (!this.tokenStorage) {
548
- return false;
549
- }
550
- const tokens = await this.tokenStorage.getTokens();
551
- return tokens !== null && tokens.access.token.length > 0;
552
- }
553
- /**
554
- * Get stored tokens
555
- *
556
- * @returns Stored tokens or null
575
+ * Trigger IoT device
557
576
  */
558
- async getStoredTokens() {
559
- if (!this.tokenStorage) {
560
- return null;
561
- }
562
- return await this.tokenStorage.getTokens();
563
- }
577
+ triggerIoTDevice: async (deviceId, config) => {
578
+ return httpClient.post(
579
+ `${EP_TRIGGER_IOT}/${deviceId}`,
580
+ config
581
+ );
582
+ },
564
583
  /**
565
- * Get stored user
566
- *
567
- * @returns Stored user or null
584
+ * Create entrance from QR code
568
585
  */
569
- async getStoredUser() {
570
- if (!this.tokenStorage) {
571
- return null;
572
- }
573
- return await this.tokenStorage.getUser();
586
+ createEntranceFromQR: (request2) => {
587
+ return httpClient.post(
588
+ EP_CREATE_QR,
589
+ request2
590
+ );
574
591
  }
575
592
  };
576
593
 
577
594
  // src/utils/location.ts
578
595
  function calculateDistance(lat1, lon1, lat2, lon2) {
579
- const R = 6371e3;
580
- const \u03C61 = lat1 * Math.PI / 180;
581
- const \u03C62 = lat2 * Math.PI / 180;
582
- const \u0394\u03C6 = (lat2 - lat1) * Math.PI / 180;
583
- const \u0394\u03BB = (lon2 - lon1) * Math.PI / 180;
584
- const a = Math.sin(\u0394\u03C6 / 2) * Math.sin(\u0394\u03C6 / 2) + Math.cos(\u03C61) * Math.cos(\u03C62) * Math.sin(\u0394\u03BB / 2) * Math.sin(\u0394\u03BB / 2);
596
+ let earthRadiusKm = 6371;
597
+ const lat1Rad = lat1 * Math.PI / 180;
598
+ const lat2Rad = lat2 * Math.PI / 180;
599
+ const dLat = (lat2 - lat1) * Math.PI / 180;
600
+ const dLon = (lon2 - lon1) * Math.PI / 180;
601
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1Rad) * Math.cos(lat2Rad) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
585
602
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
586
- return R * c;
603
+ return earthRadiusKm * c;
587
604
  }
588
605
  function checkOnLocation(targetLat, targetLon, allowedRange, userPosition) {
589
606
  if (!userPosition) {
@@ -609,20 +626,27 @@ function validateCoordinates(coords) {
609
626
  }
610
627
 
611
628
  // src/utils/validation.ts
612
- var READ_TIMEOUT = 15e3;
629
+ var READ_TIMEOUT = 3e4;
613
630
  var readRecords = [];
614
631
  function checkRepetitiveRead(code) {
615
632
  const now = Date.now();
616
- readRecords = readRecords.filter((record) => now - record.timestamp < READ_TIMEOUT);
633
+ readRecords = readRecords.filter(
634
+ (record) => now - record.timestamp < READ_TIMEOUT
635
+ );
617
636
  const recentRead = readRecords.find(
618
637
  (record) => record.code === code && now - record.timestamp < READ_TIMEOUT
619
638
  );
620
639
  if (recentRead) {
621
640
  return false;
622
641
  }
623
- readRecords.push({ code, timestamp: now });
624
642
  return true;
625
643
  }
644
+ var addQrReadRecord = (code) => {
645
+ const now = Date.now();
646
+ if (code) {
647
+ readRecords.push({ code, timestamp: now });
648
+ }
649
+ };
626
650
  function clearReadRecords() {
627
651
  readRecords = [];
628
652
  }
@@ -636,6 +660,27 @@ function validateDeviceId(id) {
636
660
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
637
661
  return uuidRegex.test(id);
638
662
  }
663
+ var shouldValidateLocation = (device) => {
664
+ return device.range_matter === "1" && !!device.latitude && !!device.longitude;
665
+ };
666
+ var validateLocation = (device, userLocation) => {
667
+ if (!shouldValidateLocation(device)) {
668
+ return { valid: true };
669
+ }
670
+ if (!userLocation) {
671
+ return { valid: false };
672
+ }
673
+ const locationCheck = checkOnLocation(
674
+ device.latitude,
675
+ device.longitude,
676
+ device.range || 100,
677
+ userLocation
678
+ );
679
+ return {
680
+ valid: locationCheck.ok,
681
+ distance: locationCheck.distance
682
+ };
683
+ };
639
684
 
640
685
  // src/utils/date.ts
641
686
  function formatISO(date = /* @__PURE__ */ new Date()) {
@@ -662,442 +707,162 @@ function parseISO(isoString) {
662
707
  return new Date(isoString);
663
708
  }
664
709
 
665
- // src/services/QRAccessService.ts
666
- var QRAccessService = class {
667
- constructor(apiClient) {
668
- this.apiClient = apiClient;
669
- }
670
- /**
671
- * Validate QR code format
672
- */
673
- validateQRFormat(code) {
674
- return validateQRCode(code);
675
- }
676
- /**
677
- * Check if location validation is required
678
- */
679
- shouldValidateLocation(device) {
680
- return device.range_matter === "1" && !!device.latitude && !!device.longitude;
681
- }
682
- /**
683
- * Validate user location against device location
684
- */
685
- validateLocation(device, userLocation) {
686
- if (!this.shouldValidateLocation(device)) {
710
+ // src/services/NFCAccessService.ts
711
+ var NfcAccessService = {
712
+ validateNFCFormat: (code) => {
713
+ return validateNFCCode(code);
714
+ },
715
+ shouldValidateLocation: (device) => {
716
+ return device?.nfc_range_matter === "1" && !!device?.latitude && !!device.longitude;
717
+ },
718
+ validateLocation: (device, userLocation) => {
719
+ if (!NfcAccessService.shouldValidateLocation(device)) {
687
720
  return { valid: true };
688
721
  }
689
722
  if (!userLocation) {
690
723
  return { valid: false };
691
724
  }
692
725
  const locationCheck = checkOnLocation(
693
- device.latitude,
694
- device.longitude,
695
- device.range || 100,
726
+ device?.latitude,
727
+ device?.longitude,
728
+ device?.nfc_range || 100,
696
729
  userLocation
697
730
  );
698
731
  return {
699
732
  valid: locationCheck.ok,
700
733
  distance: locationCheck.distance
701
734
  };
702
- }
735
+ },
703
736
  /**
704
- * Validate QR code with full checks
737
+ * Validate NFC code with full checks
705
738
  */
706
- async validateQR(options) {
707
- const { qrCode, device, userLocation, skipLocationCheck, skipRepetitiveCheck } = options;
708
- if (!this.validateQRFormat(qrCode)) {
709
- return {
710
- success: false,
711
- message: "Invalid QR code format",
712
- error: { code: "INVALID_QR_FORMAT" }
713
- };
714
- }
715
- if (!skipRepetitiveCheck && !checkRepetitiveRead(qrCode)) {
716
- return {
717
- success: false,
718
- message: "QR code was recently scanned. Please wait before scanning again.",
719
- error: { code: "REPETITIVE_READ" }
720
- };
721
- }
722
- if (!skipLocationCheck) {
723
- const locationValidation = this.validateLocation(device, userLocation);
724
- if (!locationValidation.valid) {
739
+ async validateNFC(options) {
740
+ const { device } = options;
741
+ const onlineRequestBody = {
742
+ device_id: device.id
743
+ };
744
+ if (device.is_iot) {
745
+ try {
746
+ const enteranceQrRes = await QRAccessService.createEntranceFromQR(
747
+ onlineRequestBody
748
+ );
749
+ return {
750
+ success: !!enteranceQrRes?.success,
751
+ message: "QR code validated successfully",
752
+ entrance: enteranceQrRes.data
753
+ };
754
+ } catch (error) {
725
755
  return {
726
756
  success: false,
727
- message: "You are not within the allowed range of this device",
728
- error: {
729
- code: "LOCATION_OUT_OF_RANGE",
730
- details: locationValidation.distance ? `Distance: ${locationValidation.distance.toFixed(2)}m` : void 0
731
- }
757
+ message: error.message || "Failed to validate QR code",
758
+ error: { code: "NETWORK_ERROR" }
732
759
  };
733
760
  }
734
- }
735
- try {
736
- const response = await this.apiClient.post({
737
- endpoint: EP_QR_CHECK,
738
- data: { qr_code: qrCode }
739
- });
740
- if (!response.success) {
761
+ } else {
762
+ try {
763
+ const enteranceQrRes = await QRAccessService.createEntranceFromQR(
764
+ onlineRequestBody
765
+ );
766
+ return {
767
+ success: !!enteranceQrRes?.success,
768
+ message: "QR code validated successfully",
769
+ entrance: enteranceQrRes.data
770
+ };
771
+ } catch (error) {
741
772
  return {
742
773
  success: false,
743
- message: response.message || "QR validation failed",
744
- error: { code: "API_ERROR" }
774
+ message: error.message || "Failed to validate QR code",
775
+ error: { code: "NETWORK_ERROR" }
745
776
  };
746
777
  }
747
- return {
748
- success: true,
749
- message: "QR code validated successfully",
750
- entrance: response.data
751
- };
752
- } catch (error) {
753
- return {
754
- success: false,
755
- message: error.message || "Failed to validate QR code",
756
- error: { code: "NETWORK_ERROR" }
757
- };
758
778
  }
759
779
  }
780
+ };
781
+
782
+ // src/services/DeviceAccessService.ts
783
+ var DeviceAccessService = {
760
784
  /**
761
- * Create entrance from QR code
785
+ * Get all devices
762
786
  */
763
- async createEntranceFromQR(request) {
764
- return this.apiClient.post({
765
- endpoint: EP_CREATE_QR,
766
- data: request
787
+ getDevices: async (params) => {
788
+ return httpClient.get(EP_DEVICES, {
789
+ params: params || { per_page: 100 }
767
790
  });
768
- }
791
+ },
769
792
  /**
770
- * Trigger IoT device
793
+ * Get all QR devices
771
794
  */
772
- async triggerIoTDevice(deviceId) {
773
- return this.apiClient.post({
774
- endpoint: `${EP_TRIGGER_IOT}/${deviceId}`
775
- });
776
- }
777
- };
778
-
779
- // src/services/NFCAccessService.ts
780
- var NFCAccessService = class {
781
- constructor(apiClient) {
782
- this.apiClient = apiClient;
783
- }
795
+ getQRDevices: async (params) => {
796
+ return httpClient.get(
797
+ EP_QR_DEVICES,
798
+ {
799
+ params: params || { per_page: 100 }
800
+ }
801
+ );
802
+ },
784
803
  /**
785
- * Validate NFC code format
804
+ * Get all QR devices with pagination support
786
805
  */
787
- validateNFCFormat(code) {
788
- return validateNFCCode(code);
789
- }
806
+ getAllQRDevices: async () => {
807
+ const perPage = 50;
808
+ let currentPage = 1;
809
+ let allData = [];
810
+ while (true) {
811
+ const response = await DeviceAccessService.getQRDevices({
812
+ page: currentPage,
813
+ per_page: perPage
814
+ });
815
+ if (!response.success || !response.data) {
816
+ break;
817
+ }
818
+ allData = [...allData, ...response.data];
819
+ if (!response.meta || !response.meta.total_pages) {
820
+ break;
821
+ }
822
+ if (currentPage >= response.meta.total_pages) {
823
+ break;
824
+ }
825
+ currentPage++;
826
+ }
827
+ return allData;
828
+ },
790
829
  /**
791
- * Check if location validation is required
830
+ * Get accessible QR codes for current user
792
831
  */
793
- shouldValidateLocation(device) {
794
- return device.nfc_range_matter === "1" && !!device.latitude && !!device.longitude;
795
- }
832
+ getAccessibleQRs: async () => {
833
+ return httpClient.get(
834
+ EP_QR_ACCESS
835
+ );
836
+ },
796
837
  /**
797
- * Validate user location against device location
838
+ * Get user devices
798
839
  */
799
- validateLocation(device, userLocation) {
800
- if (!this.shouldValidateLocation(device)) {
801
- return { valid: true };
802
- }
803
- if (!userLocation) {
804
- return { valid: false };
805
- }
806
- const locationCheck = checkOnLocation(
807
- device.latitude,
808
- device.longitude,
809
- device.nfc_range || 100,
810
- userLocation
811
- );
812
- return {
813
- valid: locationCheck.ok,
814
- distance: locationCheck.distance
815
- };
816
- }
817
- /**
818
- * Validate NFC code with full checks
819
- */
820
- async validateNFC(options) {
821
- const { nfcCode, device, userLocation, skipLocationCheck, skipRepetitiveCheck } = options;
822
- if (!this.validateNFCFormat(nfcCode)) {
823
- return {
824
- success: false,
825
- message: "Invalid NFC code format",
826
- error: { code: "INVALID_NFC_FORMAT" }
827
- };
828
- }
829
- if (!skipRepetitiveCheck && !checkRepetitiveRead(nfcCode)) {
830
- return {
831
- success: false,
832
- message: "NFC card was recently scanned. Please wait before scanning again.",
833
- error: { code: "REPETITIVE_READ" }
834
- };
835
- }
836
- if (!skipLocationCheck) {
837
- const locationValidation = this.validateLocation(device, userLocation);
838
- if (!locationValidation.valid) {
839
- return {
840
- success: false,
841
- message: "You are not within the allowed range of this device",
842
- error: {
843
- code: "LOCATION_OUT_OF_RANGE",
844
- details: locationValidation.distance ? `Distance: ${locationValidation.distance.toFixed(2)}m` : void 0
845
- }
846
- };
847
- }
848
- }
849
- try {
850
- const response = await this.apiClient.post({
851
- endpoint: EP_NFC_CHECK,
852
- data: { nfc_code: nfcCode }
853
- });
854
- if (!response.success) {
855
- return {
856
- success: false,
857
- message: response.message || "NFC validation failed",
858
- error: { code: "API_ERROR" }
859
- };
860
- }
861
- return {
862
- success: true,
863
- message: "NFC card validated successfully",
864
- entrance: response.data
865
- };
866
- } catch (error) {
867
- return {
868
- success: false,
869
- message: error.message || "Failed to validate NFC card",
870
- error: { code: "NETWORK_ERROR" }
871
- };
872
- }
873
- }
874
- };
875
-
876
- // src/services/CheckInService.ts
877
- var CheckInService = class {
878
- constructor(apiClient) {
879
- this.apiClient = apiClient;
880
- }
881
- /**
882
- * Get nearby branches based on user location
883
- */
884
- async getNearbyBranches(request) {
885
- const { latitude, longitude, radius } = request;
886
- if (!validateCoordinates({ latitude, longitude })) {
887
- throw new Error("Invalid coordinates provided");
888
- }
889
- return this.apiClient.get({
890
- endpoint: EP_BRANCHES,
891
- params: {
892
- latitude,
893
- longitude,
894
- ...radius && { radius }
895
- }
896
- });
897
- }
898
- /**
899
- * Check in to a branch
900
- */
901
- async checkIn(options) {
902
- const { branchId, entranceType, userId, userLocation: _userLocation } = options;
903
- try {
904
- const entranceRequest = {
905
- user_id: userId,
906
- branch_id: branchId,
907
- entrance_type: entranceType,
908
- is_manual_recording: false
909
- };
910
- const response = await this.apiClient.post({
911
- endpoint: EP_ENTRANCES,
912
- data: entranceRequest
913
- });
914
- if (!response.success) {
915
- return {
916
- success: false,
917
- message: response.message || "Check-in failed",
918
- error: { code: "API_ERROR" }
919
- };
920
- }
921
- return {
922
- success: true,
923
- message: "Check-in successful",
924
- entrance: response.data
925
- };
926
- } catch (error) {
927
- return {
928
- success: false,
929
- message: error.message || "Failed to check-in",
930
- error: { code: "NETWORK_ERROR" }
931
- };
932
- }
933
- }
934
- /**
935
- * Get branch by ID
936
- */
937
- async getBranchById(branchId) {
938
- return this.apiClient.get({
939
- endpoint: `${EP_BRANCHES}/${branchId}`
940
- });
941
- }
942
- /**
943
- * Get all branches (with pagination)
944
- */
945
- async getAllBranches(params) {
946
- return this.apiClient.get({
947
- endpoint: EP_BRANCHES,
948
- params
949
- });
950
- }
951
- };
952
-
953
- // src/services/RemoteWorkService.ts
954
- var RemoteWorkService = class {
955
- constructor(apiClient) {
956
- this.apiClient = apiClient;
957
- }
958
- /**
959
- * Log remote work entry or exit
960
- */
961
- async logRemoteWork(options) {
962
- const { userId, entranceType, timestamp, description } = options;
963
- try {
964
- const createdAt = timestamp ? typeof timestamp === "string" ? timestamp : formatISO(timestamp) : formatISO();
965
- const entranceRequest = {
966
- user_id: userId,
967
- entrance_type: entranceType,
968
- is_manual_recording: true,
969
- is_remote_work: true,
970
- created_at: createdAt,
971
- description
972
- };
973
- const response = await this.apiClient.post({
974
- endpoint: EP_ENTRANCES,
975
- data: { entrance: entranceRequest }
976
- });
977
- if (!response.success) {
978
- return {
979
- success: false,
980
- message: response.message || "Failed to log remote work",
981
- error: { code: "API_ERROR" }
982
- };
983
- }
984
- return {
985
- success: true,
986
- message: "Remote work logged successfully",
987
- entrance: response.data
988
- };
989
- } catch (error) {
990
- return {
991
- success: false,
992
- message: error.message || "Failed to log remote work",
993
- error: { code: "NETWORK_ERROR" }
994
- };
995
- }
996
- }
997
- /**
998
- * Log remote work entry
999
- */
1000
- async logEntry(options) {
1001
- return this.logRemoteWork({
1002
- ...options,
1003
- entranceType: 0 /* ENTRY */
1004
- });
1005
- }
1006
- /**
1007
- * Log remote work exit
1008
- */
1009
- async logExit(options) {
1010
- return this.logRemoteWork({
1011
- ...options,
1012
- entranceType: 1 /* EXIT */
1013
- });
1014
- }
1015
- };
1016
-
1017
- // src/services/DeviceAccessService.ts
1018
- var DeviceAccessService = class {
1019
- constructor(apiClient) {
1020
- this.apiClient = apiClient;
1021
- }
1022
- /**
1023
- * Get all devices
1024
- */
1025
- async getDevices(params) {
1026
- return this.apiClient.get({
1027
- endpoint: EP_DEVICES,
1028
- params: params || { per_page: 100 }
1029
- });
1030
- }
1031
- /**
1032
- * Get all QR devices
1033
- */
1034
- async getQRDevices(params) {
1035
- return this.apiClient.get({
1036
- endpoint: EP_QR_DEVICES,
1037
- params: params || { per_page: 100 }
1038
- });
1039
- }
1040
- /**
1041
- * Get all QR devices with pagination support
1042
- */
1043
- async getAllQRDevices() {
1044
- const perPage = 50;
1045
- let currentPage = 1;
1046
- let allData = [];
1047
- while (true) {
1048
- const response = await this.getQRDevices({
1049
- page: currentPage,
1050
- per_page: perPage
1051
- });
1052
- if (!response.success || !response.data) {
1053
- break;
1054
- }
1055
- allData = [...allData, ...response.data];
1056
- if (!response.meta || !response.meta.total_pages) {
1057
- break;
1058
- }
1059
- if (currentPage >= response.meta.total_pages) {
1060
- break;
1061
- }
1062
- currentPage++;
1063
- }
1064
- return allData;
1065
- }
1066
- /**
1067
- * Get accessible QR codes for current user
1068
- */
1069
- async getAccessibleQRs() {
1070
- return this.apiClient.get({
1071
- endpoint: EP_QR_ACCESS
1072
- });
1073
- }
1074
- /**
1075
- * Get user devices
1076
- */
1077
- async getUserDevices(request) {
1078
- const { userId, page, per_page } = request;
1079
- return this.apiClient.get({
1080
- endpoint: `${EP_USERS}/${userId}/devices`,
1081
- params: {
1082
- ...page && { page },
1083
- ...per_page && { per_page }
840
+ getUserDevices: async (request2) => {
841
+ const { userId, page, per_page } = request2;
842
+ return httpClient.get(
843
+ `${EP_USERS}/${userId}/devices`,
844
+ {
845
+ params: {
846
+ ...page && { page },
847
+ ...per_page && { per_page }
848
+ }
1084
849
  }
1085
- });
1086
- }
850
+ );
851
+ },
1087
852
  /**
1088
853
  * Get device by ID
1089
854
  */
1090
- async getDeviceById(deviceId) {
1091
- return this.apiClient.get({
1092
- endpoint: `${EP_DEVICES}/${deviceId}`
1093
- });
1094
- }
855
+ getDeviceById: async (deviceId) => {
856
+ return httpClient.get(
857
+ `${EP_DEVICES}/${deviceId}`
858
+ );
859
+ },
1095
860
  /**
1096
861
  * Check if user has access to a device
1097
862
  */
1098
- async checkDeviceAccess(deviceId) {
863
+ checkDeviceAccess: async (deviceId) => {
1099
864
  try {
1100
- const response = await this.getAccessibleQRs();
865
+ const response = await DeviceAccessService.getAccessibleQRs();
1101
866
  if (!response.success || !response.data) {
1102
867
  return false;
1103
868
  }
@@ -1105,24 +870,25 @@ var DeviceAccessService = class {
1105
870
  } catch {
1106
871
  return false;
1107
872
  }
1108
- }
873
+ },
1109
874
  /**
1110
875
  * Find QR device by QR code ID
1111
876
  */
1112
- async findDeviceByQRCode(qrCodeId) {
877
+ findDeviceByQRCode: async (qrCodeId) => {
1113
878
  try {
1114
- const devices = await this.getAllQRDevices();
1115
- return devices.find((device) => device.qr_code_id === qrCodeId);
879
+ const devices = await DeviceAccessService.getAllQRDevices();
880
+ const qr = devices.find((device) => device.qr_code_id === qrCodeId);
881
+ return qr;
1116
882
  } catch {
1117
883
  return void 0;
1118
884
  }
1119
- }
885
+ },
1120
886
  /**
1121
887
  * Find QR device by NFC code
1122
888
  */
1123
- async findDeviceByNFCCode(nfcCode) {
889
+ findDeviceByNFCCode: async (nfcCode) => {
1124
890
  try {
1125
- const devices = await this.getAllQRDevices();
891
+ const devices = await DeviceAccessService.getAllQRDevices();
1126
892
  return devices.find((device) => device.nfc_code === nfcCode);
1127
893
  } catch {
1128
894
  return void 0;
@@ -1217,41 +983,35 @@ var LocationService = class {
1217
983
  return this.logLocationVerification(log);
1218
984
  }
1219
985
  };
1220
-
1221
- // src/providers/PassgageAccessProvider.tsx
1222
- var import_react = __toESM(require("react"));
1223
-
1224
- // src/utils/secureStorage.ts
1225
- var Keychain = __toESM(require("react-native-keychain"));
1226
986
  var STORAGE_KEYS = {
1227
987
  TOKENS: "passgage_auth_tokens",
1228
988
  USER: "passgage_user_info"
1229
989
  };
1230
- var SecureStorage = class {
990
+ var SecureStorage = {
1231
991
  /**
1232
992
  * Save tokens to secure storage
1233
993
  */
1234
- async saveTokens(tokens) {
994
+ saveTokens: async (tokens) => {
1235
995
  try {
1236
- await Keychain.setGenericPassword(
996
+ await Keychain__namespace.setGenericPassword(
1237
997
  STORAGE_KEYS.TOKENS,
1238
998
  JSON.stringify(tokens),
1239
999
  {
1240
1000
  service: STORAGE_KEYS.TOKENS,
1241
- accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED
1001
+ accessible: Keychain__namespace.ACCESSIBLE.WHEN_UNLOCKED
1242
1002
  }
1243
1003
  );
1244
1004
  } catch (error) {
1245
1005
  console.error("Failed to save tokens to secure storage:", error);
1246
1006
  throw new Error("Failed to save tokens");
1247
1007
  }
1248
- }
1008
+ },
1249
1009
  /**
1250
1010
  * Get tokens from secure storage
1251
1011
  */
1252
- async getTokens() {
1012
+ getTokens: async () => {
1253
1013
  try {
1254
- const credentials = await Keychain.getGenericPassword({
1014
+ const credentials = await Keychain__namespace.getGenericPassword({
1255
1015
  service: STORAGE_KEYS.TOKENS
1256
1016
  });
1257
1017
  if (!credentials) {
@@ -1263,43 +1023,43 @@ var SecureStorage = class {
1263
1023
  console.error("Failed to get tokens from secure storage:", error);
1264
1024
  return null;
1265
1025
  }
1266
- }
1026
+ },
1267
1027
  /**
1268
1028
  * Clear tokens from secure storage
1269
1029
  */
1270
- async clearTokens() {
1030
+ clearTokens: async () => {
1271
1031
  try {
1272
- await Keychain.resetGenericPassword({
1032
+ await Keychain__namespace.resetGenericPassword({
1273
1033
  service: STORAGE_KEYS.TOKENS
1274
1034
  });
1275
1035
  } catch (error) {
1276
1036
  console.error("Failed to clear tokens from secure storage:", error);
1277
1037
  }
1278
- }
1038
+ },
1279
1039
  /**
1280
1040
  * Save user information
1281
1041
  */
1282
- async saveUser(user) {
1042
+ saveUser: async (user) => {
1283
1043
  try {
1284
- await Keychain.setGenericPassword(
1044
+ await Keychain__namespace.setGenericPassword(
1285
1045
  STORAGE_KEYS.USER,
1286
1046
  JSON.stringify(user),
1287
1047
  {
1288
1048
  service: STORAGE_KEYS.USER,
1289
- accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED
1049
+ accessible: Keychain__namespace.ACCESSIBLE.WHEN_UNLOCKED
1290
1050
  }
1291
1051
  );
1292
1052
  } catch (error) {
1293
1053
  console.error("Failed to save user to secure storage:", error);
1294
1054
  throw new Error("Failed to save user");
1295
1055
  }
1296
- }
1056
+ },
1297
1057
  /**
1298
1058
  * Get user information
1299
1059
  */
1300
- async getUser() {
1060
+ getUser: async () => {
1301
1061
  try {
1302
- const credentials = await Keychain.getGenericPassword({
1062
+ const credentials = await Keychain__namespace.getGenericPassword({
1303
1063
  service: STORAGE_KEYS.USER
1304
1064
  });
1305
1065
  if (!credentials) {
@@ -1311,269 +1071,579 @@ var SecureStorage = class {
1311
1071
  console.error("Failed to get user from secure storage:", error);
1312
1072
  return null;
1313
1073
  }
1314
- }
1074
+ },
1315
1075
  /**
1316
1076
  * Clear user information
1317
1077
  */
1318
- async clearUser() {
1078
+ clearUser: async () => {
1319
1079
  try {
1320
- await Keychain.resetGenericPassword({
1080
+ await Keychain__namespace.resetGenericPassword({
1321
1081
  service: STORAGE_KEYS.USER
1322
1082
  });
1323
1083
  } catch (error) {
1324
1084
  console.error("Failed to clear user from secure storage:", error);
1325
1085
  }
1326
- }
1086
+ },
1327
1087
  /**
1328
1088
  * Clear all data (tokens + user)
1329
1089
  */
1330
- async clearAll() {
1331
- await this.clearTokens();
1332
- await this.clearUser();
1090
+ clearAll: async () => {
1091
+ await SecureStorage.clearTokens();
1092
+ await SecureStorage.clearUser();
1333
1093
  }
1334
1094
  };
1335
- function createSecureStorage() {
1336
- return new SecureStorage();
1337
- }
1095
+ var qrScannerStore = zustand.create((set, get) => ({
1096
+ loading: false,
1097
+ error: null,
1098
+ qrDevices: [],
1099
+ qrAccessDevices: [],
1100
+ handleQrAccess: async () => {
1101
+ const res = await DeviceAccessService.getAccessibleQRs();
1102
+ if (res.data) {
1103
+ set({ qrAccessDevices: res.data.qr_ids });
1104
+ }
1105
+ },
1106
+ fetchQrDevicesAndAccess: async () => {
1107
+ try {
1108
+ const [qrDevicesRes, qrAccessRes] = await Promise.all([
1109
+ DeviceAccessService.getAllQRDevices(),
1110
+ DeviceAccessService.getAccessibleQRs()
1111
+ ]);
1112
+ if (qrDevicesRes && qrDevicesRes.length > 0 && qrAccessRes) {
1113
+ set({
1114
+ qrDevices: qrDevicesRes,
1115
+ qrAccessDevices: qrAccessRes.data?.qr_ids
1116
+ });
1117
+ }
1118
+ } catch (error) {
1119
+ }
1120
+ }
1121
+ }));
1122
+ var locationStore = zustand.create((set, get) => ({
1123
+ location: null,
1124
+ error: null,
1125
+ loading: false,
1126
+ refreshLocation: (config = {
1127
+ enableHighAccuracy: true,
1128
+ timeout: 15e3,
1129
+ maximumAge: 1e4
1130
+ }) => {
1131
+ Geolocation2__default.default.getCurrentPosition(
1132
+ (position) => {
1133
+ set({
1134
+ loading: false,
1135
+ error: null,
1136
+ location: {
1137
+ latitude: position.coords.latitude,
1138
+ longitude: position.coords.longitude,
1139
+ accuracy: position.coords.accuracy,
1140
+ altitude: position.coords.altitude ?? void 0,
1141
+ altitudeAccuracy: position.coords.altitudeAccuracy ?? void 0,
1142
+ heading: position.coords.heading ?? void 0,
1143
+ speed: position.coords.speed ?? void 0
1144
+ }
1145
+ });
1146
+ },
1147
+ (err) => {
1148
+ set({
1149
+ loading: false,
1150
+ error: err
1151
+ });
1152
+ },
1153
+ config
1154
+ );
1155
+ }
1156
+ }));
1338
1157
 
1339
- // src/providers/PassgageAccessProvider.tsx
1340
- var PassgageAccessContext = (0, import_react.createContext)(void 0);
1341
- function PassgageAccessProvider({
1342
- children,
1343
- baseURL,
1344
- token,
1345
- apiVersion = "v2",
1346
- timeout = 3e4,
1347
- onUnauthorized,
1348
- onError
1349
- }) {
1350
- const config = {
1351
- baseURL,
1352
- token,
1353
- apiVersion,
1354
- timeout,
1355
- onUnauthorized,
1356
- onError
1357
- };
1358
- const { apiClient, services } = (0, import_react.useMemo)(() => {
1359
- const secureStorage = createSecureStorage();
1360
- let authService;
1361
- const client = createApiClient({
1362
- baseURL: config.baseURL,
1363
- token: config.token,
1364
- apiVersion: config.apiVersion,
1365
- timeout: config.timeout,
1366
- onUnauthorized: config.onUnauthorized,
1367
- onError: config.onError,
1368
- onTokenRefreshNeeded: async () => {
1369
- const storedTokens = await authService.getStoredTokens();
1370
- if (!storedTokens) {
1371
- return null;
1372
- }
1373
- const result = await authService.refreshToken(storedTokens.refresh.token);
1374
- if (result.success) {
1375
- return result.tokens.access.token;
1376
- }
1377
- return null;
1158
+ // src/utils/flowHelpers.ts
1159
+ var enteranceFlow = async (data, options) => {
1160
+ const location = locationStore.getState().location;
1161
+ const qrAccessDevices = qrScannerStore.getState().qrAccessDevices;
1162
+ const { qrCode, device, isQrCode, nfcCode = "" } = data;
1163
+ if (isQrCode ? !validateQRCode(qrCode) : validateNFCCode(nfcCode)) {
1164
+ return {
1165
+ success: false,
1166
+ message: "Invalid QR code format",
1167
+ error: { code: "INVALID_QR_FORMAT" }
1168
+ };
1169
+ }
1170
+ const checkAccessible = isQrCode ? qrAccessDevices.find((qrAccessDevice) => qrAccessDevice === qrCode) : qrAccessDevices.find((qrAccessDevice) => qrAccessDevice === nfcCode);
1171
+ if (!checkAccessible) {
1172
+ return {
1173
+ success: false,
1174
+ message: "You do not have permission. Please contact your administrator",
1175
+ error: {
1176
+ code: "QR_ACCESS_DENIED"
1378
1177
  }
1379
- });
1380
- authService = new AuthService(client);
1381
- authService.setTokenStorage(secureStorage);
1382
- const allServices = {
1383
- authService,
1384
- qrAccessService: new QRAccessService(client),
1385
- nfcAccessService: new NFCAccessService(client),
1386
- checkInService: new CheckInService(client),
1387
- remoteWorkService: new RemoteWorkService(client),
1388
- deviceAccessService: new DeviceAccessService(client),
1389
- locationService: new LocationService(client)
1390
1178
  };
1179
+ }
1180
+ if (!options.skipRepetitiveCheck && !checkRepetitiveRead(isQrCode ? qrCode : nfcCode)) {
1391
1181
  return {
1392
- apiClient: client,
1393
- services: allServices
1182
+ success: false,
1183
+ message: "QR code was recently scanned. Please wait before scanning again.",
1184
+ error: { code: "REPETITIVE_READ" }
1394
1185
  };
1395
- }, [config.baseURL, config.token, config.apiVersion, config.timeout, config.onUnauthorized, config.onError]);
1396
- const setToken = (newToken) => {
1397
- apiClient.setToken(newToken);
1398
- };
1399
- const clearToken = () => {
1400
- apiClient.clearToken();
1401
- };
1402
- const contextValue = {
1403
- apiClient,
1404
- ...services,
1405
- config,
1406
- setToken,
1407
- clearToken
1408
- };
1409
- return /* @__PURE__ */ import_react.default.createElement(PassgageAccessContext.Provider, { value: contextValue }, children);
1410
- }
1411
- function usePassgageAccess() {
1412
- const context = (0, import_react.useContext)(PassgageAccessContext);
1413
- if (!context) {
1414
- throw new Error(
1415
- "usePassgageAccess must be used within a PassgageAccessProvider"
1416
- );
1417
1186
  }
1418
- return context;
1419
- }
1420
-
1421
- // src/hooks/usePassgageAuth.ts
1422
- var import_react2 = require("react");
1423
- function usePassgageAuth(options = {}) {
1424
- const {
1425
- onLoginSuccess,
1426
- onLoginError,
1427
- onLogoutSuccess,
1428
- autoRestore = true
1429
- } = options;
1430
- const { authService } = usePassgageAccess();
1431
- const [isAuthenticated, setIsAuthenticated] = (0, import_react2.useState)(false);
1432
- const [user, setUser] = (0, import_react2.useState)(null);
1433
- const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
1434
- const [error, setError] = (0, import_react2.useState)(null);
1435
- (0, import_react2.useEffect)(() => {
1436
- if (!autoRestore) {
1437
- return;
1438
- }
1439
- const restoreAuth = async () => {
1440
- try {
1441
- setIsLoading(true);
1442
- const authenticated = await authService.isAuthenticated();
1443
- if (authenticated) {
1444
- const storedTokens = await authService.getStoredTokens();
1445
- const storedUser = await authService.getStoredUser();
1446
- if (storedTokens && storedUser) {
1447
- authService["apiClient"].setToken(storedTokens.access.token);
1448
- setIsAuthenticated(true);
1449
- setUser(storedUser);
1450
- try {
1451
- const userResult = await authService.getCurrentUser();
1452
- if (userResult.success) {
1453
- setUser(userResult.user);
1454
- }
1455
- } catch (error2) {
1456
- console.warn("Failed to fetch fresh user info:", error2);
1457
- }
1458
- }
1187
+ if (!options.skipLocationCheck) {
1188
+ const locationValidation = validateLocation(device, location ?? void 0);
1189
+ if (!locationValidation.valid) {
1190
+ return {
1191
+ success: false,
1192
+ message: `You are not within the allowed range of this device${location?.latitude},${location?.longitude}`,
1193
+ error: {
1194
+ code: "LOCATION_OUT_OF_RANGE",
1195
+ details: locationValidation.distance ? `Distance: ${locationValidation.distance.toFixed(2)}m` : void 0
1459
1196
  }
1460
- } catch (error2) {
1461
- console.error("Failed to restore authentication:", error2);
1462
- setError(error2.message || "Failed to restore authentication");
1463
- } finally {
1464
- setIsLoading(false);
1465
- }
1466
- };
1467
- restoreAuth();
1468
- }, [authService, autoRestore]);
1469
- const login = (0, import_react2.useCallback)(
1470
- async (credentials) => {
1471
- try {
1472
- setIsLoading(true);
1473
- setError(null);
1474
- const result = await authService.login(credentials);
1475
- if (result.success) {
1476
- setIsAuthenticated(true);
1477
- setUser(result.user || null);
1478
- if (onLoginSuccess) {
1479
- onLoginSuccess(result.user);
1480
- }
1481
- } else {
1482
- setError(result.error);
1483
- if (onLoginError) {
1484
- onLoginError(result.error);
1197
+ };
1198
+ }
1199
+ }
1200
+ const onlineRequestBody = {
1201
+ device_id: device?.id ?? ""
1202
+ };
1203
+ if (device?.is_iot) {
1204
+ try {
1205
+ const enteranceResIot = await QRAccessService.triggerIoTDevice(device.id);
1206
+ if (enteranceResIot.success) {
1207
+ try {
1208
+ const enteranceQrRes = await QRAccessService.createEntranceFromQR(
1209
+ onlineRequestBody
1210
+ );
1211
+ if (enteranceQrRes.success) {
1212
+ addQrReadRecord(qrCode);
1213
+ return {
1214
+ success: !!enteranceQrRes?.success,
1215
+ message: enteranceQrRes.success ? "Enterance validated successfully" : "Enterance validation failed",
1216
+ entrance: enteranceQrRes.data
1217
+ };
1218
+ } else {
1219
+ return {
1220
+ success: false,
1221
+ message: enteranceQrRes.message ?? "Trigger IOT validation failed"
1222
+ };
1485
1223
  }
1224
+ } catch (error) {
1225
+ return {
1226
+ success: false,
1227
+ message: error?.message ?? "Qr enterance failed"
1228
+ };
1486
1229
  }
1487
- return result;
1488
- } catch (error2) {
1489
- const errorMessage = error2.message || "An error occurred during login";
1490
- setError(errorMessage);
1491
- if (onLoginError) {
1492
- onLoginError(errorMessage);
1493
- }
1230
+ } else {
1494
1231
  return {
1495
1232
  success: false,
1496
- error: errorMessage,
1497
- code: "UNKNOWN_ERROR"
1233
+ message: enteranceResIot.message ?? "Trigger IOT validation failed"
1498
1234
  };
1499
- } finally {
1500
- setIsLoading(false);
1501
- }
1502
- },
1503
- [authService, onLoginSuccess, onLoginError]
1504
- );
1505
- const logout = (0, import_react2.useCallback)(async () => {
1506
- try {
1507
- setIsLoading(true);
1508
- setError(null);
1509
- await authService.logout();
1510
- setIsAuthenticated(false);
1511
- setUser(null);
1512
- if (onLogoutSuccess) {
1513
- onLogoutSuccess();
1514
1235
  }
1515
- } catch (error2) {
1516
- const errorMessage = error2.message || "An error occurred during logout";
1517
- setError(errorMessage);
1518
- console.error("Logout failed:", error2);
1519
- } finally {
1520
- setIsLoading(false);
1236
+ } catch (error) {
1237
+ return {
1238
+ success: false,
1239
+ message: error ?? "Trigger IOT validation failed"
1240
+ };
1521
1241
  }
1522
- }, [authService, onLogoutSuccess]);
1523
- const refreshToken = (0, import_react2.useCallback)(async () => {
1242
+ } else {
1524
1243
  try {
1525
- const storedTokens = await authService.getStoredTokens();
1526
- if (!storedTokens) {
1244
+ const enteranceQrRes = await QRAccessService.createEntranceFromQR(
1245
+ onlineRequestBody
1246
+ );
1247
+ addQrReadRecord(qrCode);
1248
+ return {
1249
+ success: !!enteranceQrRes?.success,
1250
+ message: enteranceQrRes.success ? "QR code validated successfully" : "QR code validation failed",
1251
+ entrance: enteranceQrRes.data
1252
+ };
1253
+ } catch (error) {
1254
+ return {
1255
+ success: false,
1256
+ message: error.message || "Failed to validate QR code",
1257
+ error: { code: "NETWORK_ERROR" }
1258
+ };
1259
+ }
1260
+ }
1261
+ };
1262
+ var loginSuccessFlow = async (result) => {
1263
+ qrScannerStore.getState().fetchQrDevicesAndAccess();
1264
+ if (result.success) {
1265
+ await SecureStorage.saveTokens(result.tokens);
1266
+ if (result.user) {
1267
+ await SecureStorage.saveUser?.(result.user);
1268
+ }
1269
+ }
1270
+ };
1271
+
1272
+ // src/stores/authStore.ts
1273
+ var useAuthStore = zustand.create((set, get) => ({
1274
+ loading: false,
1275
+ error: null,
1276
+ authStatus: false,
1277
+ user: null,
1278
+ restoreAuth: async () => {
1279
+ const tokens = await SecureStorage.getTokens?.();
1280
+ try {
1281
+ set({ loading: true });
1282
+ const isAuthenticated = tokens !== null && tokens?.access?.token?.length > 0;
1283
+ if (isAuthenticated) {
1284
+ const storedTokens = await SecureStorage.getTokens?.();
1285
+ const storedUser = await SecureStorage.getUser?.();
1286
+ if (storedTokens && storedUser) {
1287
+ setTokenToHttpClient(storedTokens.access.token);
1288
+ set({
1289
+ user: storedUser,
1290
+ authStatus: true
1291
+ });
1292
+ try {
1293
+ const userResult = await AuthService.getCurrentUser();
1294
+ if (userResult.success) {
1295
+ set({
1296
+ user: userResult.user
1297
+ });
1298
+ qrScannerStore.getState().fetchQrDevicesAndAccess();
1299
+ }
1300
+ } catch (error) {
1301
+ console.warn("Failed to fetch fresh user info:", error);
1302
+ }
1303
+ }
1304
+ }
1305
+ } catch (error) {
1306
+ console.error("Failed to restore authentication:", error);
1307
+ set({ error: error.message || "Failed to restore authentication" });
1308
+ } finally {
1309
+ set({ loading: false });
1310
+ }
1311
+ },
1312
+ login: async (credentials, resolve, reject) => {
1313
+ try {
1314
+ set({ loading: true, error: null });
1315
+ const result = await AuthService.login(credentials);
1316
+ if (result.success) {
1317
+ resolve?.(result.user);
1318
+ loginSuccessFlow(result);
1319
+ set({ authStatus: true, user: result.user || null });
1320
+ } else {
1321
+ get().logout();
1322
+ reject?.(result.error);
1323
+ set({ error: result.error });
1324
+ }
1325
+ } catch (error) {
1326
+ get().logout();
1327
+ const errorMessage = error.message || "An error occurred during login";
1328
+ set({ error: errorMessage });
1329
+ reject?.(errorMessage);
1330
+ } finally {
1331
+ set({ loading: false });
1332
+ }
1333
+ },
1334
+ loginWithAzure: async (credentials, resolve, reject) => {
1335
+ try {
1336
+ set({ loading: true, error: null });
1337
+ const result = await AuthService.loginWithAzure(credentials);
1338
+ if (result.success) {
1339
+ loginSuccessFlow(result);
1340
+ resolve?.(result.user);
1341
+ set({ authStatus: true, user: result.user || null });
1342
+ } else {
1343
+ reject?.(result.error);
1344
+ get().logout();
1345
+ set({ error: result.error });
1346
+ }
1347
+ } catch (error) {
1348
+ const errorMessage = error.message || "An error occurred during Azure login";
1349
+ get().logout();
1350
+ set({ error: errorMessage });
1351
+ reject?.(errorMessage);
1352
+ } finally {
1353
+ set({ loading: false });
1354
+ }
1355
+ },
1356
+ logout: async (resolve) => {
1357
+ try {
1358
+ set({
1359
+ loading: true,
1360
+ error: null
1361
+ });
1362
+ await SecureStorage.clearTokens?.();
1363
+ await SecureStorage.clearUser?.();
1364
+ set({ authStatus: false, user: null });
1365
+ resolve?.();
1366
+ } catch (error) {
1367
+ const errorMessage = error.message || "An error occurred during logout";
1368
+ set({ error: errorMessage });
1369
+ console.error("Logout failed:", error);
1370
+ } finally {
1371
+ set({ loading: false });
1372
+ }
1373
+ },
1374
+ refreshToken: async () => {
1375
+ try {
1376
+ const storedTokens = await SecureStorage.getTokens?.();
1377
+ if (!storedTokens) {
1527
1378
  return false;
1528
1379
  }
1529
- const result = await authService.refreshToken(storedTokens.refresh.token);
1380
+ const result = await AuthService.refreshToken(storedTokens.refresh.token);
1530
1381
  if (result.success) {
1531
1382
  return true;
1532
1383
  } else {
1533
- await logout();
1384
+ await get().logout();
1534
1385
  return false;
1535
1386
  }
1536
- } catch (error2) {
1537
- console.error("Token refresh failed:", error2);
1538
- await logout();
1387
+ } catch (error) {
1388
+ console.error("Token refresh failed:", error);
1389
+ await get().logout();
1539
1390
  return false;
1540
1391
  }
1541
- }, [authService, logout]);
1542
- const clearError = (0, import_react2.useCallback)(() => {
1543
- setError(null);
1392
+ },
1393
+ clearError: () => {
1394
+ set({ error: null });
1395
+ }
1396
+ }));
1397
+ var PassgageAccessProvideContext = React.createContext(void 0);
1398
+ function PassgageAccessProvider(props) {
1399
+ const {
1400
+ children,
1401
+ baseURL,
1402
+ msalToken,
1403
+ apiVersion = "v2",
1404
+ timeout = 3e4,
1405
+ rememberUser = true,
1406
+ onUnauthorized = () => {
1407
+ },
1408
+ locationPermissionErrorCallback = () => {
1409
+ },
1410
+ getLocationErrorCallback = () => {
1411
+ }
1412
+ } = props;
1413
+ const useLocationStore = locationStore();
1414
+ const authStore = useAuthStore();
1415
+ React.useEffect(() => {
1416
+ const msalTokenInitFlow = async () => {
1417
+ try {
1418
+ await authStore.loginWithAzure(
1419
+ {
1420
+ id_token: msalToken ?? "",
1421
+ device_type: reactNative.Platform.OS === "ios" ? "ios" : "android"
1422
+ },
1423
+ () => {
1424
+ },
1425
+ (error) => {
1426
+ console.error("Failed to login with Azure:", error);
1427
+ authStore.logout();
1428
+ }
1429
+ );
1430
+ } catch (error) {
1431
+ console.error("Failed to login with Azure:", error);
1432
+ authStore.logout();
1433
+ }
1434
+ };
1435
+ const LocationPermission = reactNative.Platform.select({
1436
+ android: RNPermissions.PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
1437
+ ios: RNPermissions.PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
1438
+ default: RNPermissions.PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
1439
+ });
1440
+ if (LocationPermission) {
1441
+ RNPermissions__default.default.check(LocationPermission).then((status) => {
1442
+ switch (status) {
1443
+ case RNPermissions.RESULTS.DENIED:
1444
+ RNPermissions.request(LocationPermission).then(() => {
1445
+ useLocationStore.refreshLocation();
1446
+ });
1447
+ break;
1448
+ case RNPermissions.RESULTS.BLOCKED:
1449
+ case RNPermissions.RESULTS.UNAVAILABLE:
1450
+ case RNPermissions.RESULTS.GRANTED:
1451
+ case RNPermissions.RESULTS.LIMITED:
1452
+ useLocationStore.refreshLocation();
1453
+ break;
1454
+ }
1455
+ }).catch((error) => {
1456
+ locationPermissionErrorCallback(error);
1457
+ console.error(error);
1458
+ });
1459
+ }
1460
+ createHttpClient({ apiVersion, baseURL, timeout });
1461
+ if (msalToken) {
1462
+ msalTokenInitFlow();
1463
+ } else {
1464
+ authStore.logout();
1465
+ onUnauthorized({
1466
+ name: "Unauthorized",
1467
+ message: "MSAL Token is required"
1468
+ });
1469
+ }
1470
+ if (rememberUser) {
1471
+ authStore.restoreAuth();
1472
+ }
1544
1473
  }, []);
1474
+ React.useEffect(() => {
1475
+ if (useLocationStore.error) {
1476
+ getLocationErrorCallback(useLocationStore.error);
1477
+ }
1478
+ }, [useLocationStore.error]);
1479
+ return /* @__PURE__ */ React__default.default.createElement(PassgageAccessProvideContext.Provider, { value: { ...props } }, children);
1480
+ }
1481
+ var usePassgageAccessContext = () => {
1482
+ const ctx = React.useContext(PassgageAccessProvideContext);
1483
+ if (!ctx) {
1484
+ throw new Error(
1485
+ "usePassgageAccessContext must be used inside AuthProvider"
1486
+ );
1487
+ }
1488
+ return ctx;
1489
+ };
1490
+ var usePassgageQRScanner = (payload) => {
1491
+ const [isLoading, setIsLoading] = React.useState(false);
1492
+ const [error, setError] = React.useState(null);
1493
+ const { qrDevices } = qrScannerStore();
1494
+ const scan = async (qrCode, device) => {
1495
+ setIsLoading(true);
1496
+ setError(null);
1497
+ try {
1498
+ let qrDevice = device;
1499
+ if (!qrDevice) {
1500
+ qrDevice = qrDevices.find((item) => item.qr_code_id === qrCode);
1501
+ if (!qrDevice) {
1502
+ payload.onError?.(
1503
+ error ?? { message: "QR Device not found", success: false }
1504
+ );
1505
+ return;
1506
+ }
1507
+ }
1508
+ const result = await enteranceFlow(
1509
+ {
1510
+ device: qrDevice,
1511
+ qrCode,
1512
+ isQrCode: true
1513
+ },
1514
+ payload.options
1515
+ );
1516
+ if (!result.success) {
1517
+ payload.onError?.(result);
1518
+ } else {
1519
+ payload.onSuccess?.(result.entrance);
1520
+ }
1521
+ } catch (err) {
1522
+ const errorObj = {
1523
+ success: false,
1524
+ message: err?.message || "Qr scan failed",
1525
+ error: { code: "QR_SCAN_FAILED" }
1526
+ };
1527
+ setError(errorObj);
1528
+ payload.onError?.(errorObj);
1529
+ } finally {
1530
+ setIsLoading(false);
1531
+ }
1532
+ };
1545
1533
  return {
1546
- login,
1547
- logout,
1548
- refreshToken,
1549
- isAuthenticated,
1550
- user,
1534
+ scan,
1551
1535
  isLoading,
1536
+ error
1537
+ };
1538
+ };
1539
+ var bigInt = __require("big-integer");
1540
+ var reversedHexToDec = (reversedHex) => {
1541
+ try {
1542
+ reversedHex = reversedHex.replace(/\s+/g, "");
1543
+ let originalHex = "";
1544
+ for (let i = reversedHex.length; i > 0; i -= 2) {
1545
+ originalHex += reversedHex.substring(i - 2, i);
1546
+ }
1547
+ let decimalValue = bigInt(originalHex, 16);
1548
+ return decimalValue.toString();
1549
+ } catch (error) {
1550
+ return reversedHex;
1551
+ }
1552
+ };
1553
+ function usePassgageNFCScanner(payload) {
1554
+ const [supportNFC, setSupportNFC] = React.useState();
1555
+ const [isScanning, setIsScanning] = React.useState(false);
1556
+ const [nfcData, setNfcData] = React.useState();
1557
+ const { qrDevices } = qrScannerStore();
1558
+ const [error, setError] = React.useState(null);
1559
+ React.useEffect(() => {
1560
+ NfcManager__default.default.isSupported().then((supported) => {
1561
+ if (supported) {
1562
+ setSupportNFC(true);
1563
+ } else {
1564
+ setSupportNFC(false);
1565
+ }
1566
+ });
1567
+ return () => {
1568
+ NfcManager__default.default.cancelTechnologyRequest();
1569
+ };
1570
+ }, []);
1571
+ const stopScanning = async () => {
1572
+ try {
1573
+ NfcManager__default.default.cancelTechnologyRequest().finally(() => {
1574
+ setIsScanning(false);
1575
+ });
1576
+ } catch {
1577
+ }
1578
+ };
1579
+ const handleNFCTag = async (tag) => {
1580
+ if (!tag.id) {
1581
+ return;
1582
+ }
1583
+ try {
1584
+ const nfcCode = reversedHexToDec(tag.id);
1585
+ if (reactNative.Platform.OS === "ios") {
1586
+ await NfcManager__default.default.cancelTechnologyRequest();
1587
+ }
1588
+ const device = qrDevices.find((device2) => device2.nfc_code === nfcCode);
1589
+ if (!device) {
1590
+ throw new Error("NFC device not found");
1591
+ }
1592
+ const result = await enteranceFlow(
1593
+ {
1594
+ device,
1595
+ nfcCode,
1596
+ isQrCode: false
1597
+ },
1598
+ payload.options
1599
+ );
1600
+ if (!result.success) {
1601
+ throw new Error(result.message);
1602
+ }
1603
+ payload.onSuccess?.(result.entrance);
1604
+ stopScanning();
1605
+ } catch (err) {
1606
+ const error2 = err;
1607
+ setError(error2);
1608
+ payload.onError?.(error2);
1609
+ stopScanning();
1610
+ }
1611
+ };
1612
+ const startScanning = async () => {
1613
+ await NfcManager__default.default.requestTechnology(NfcManager.NfcTech.Ndef, {
1614
+ invalidateAfterFirstRead: true
1615
+ });
1616
+ await NfcManager__default.default.getTag().then((tag) => {
1617
+ setNfcData(tag?.id ?? "");
1618
+ handleNFCTag(tag || {});
1619
+ }).catch(() => false);
1620
+ NfcManager__default.default.cancelTechnologyRequest();
1621
+ setIsScanning(true);
1622
+ setError(null);
1623
+ };
1624
+ return {
1625
+ nfcData,
1626
+ supportNFC,
1627
+ startScanning,
1628
+ stopScanning,
1552
1629
  error,
1553
- clearError
1630
+ isScanning
1554
1631
  };
1555
1632
  }
1556
-
1557
- // src/hooks/usePassgageQRScanner.ts
1558
- var import_react4 = require("react");
1559
-
1560
- // src/hooks/useLocation.ts
1561
- var import_react3 = require("react");
1562
- var import_geolocation = __toESM(require("@react-native-community/geolocation"));
1563
1633
  function useLocation(options = {}) {
1564
- const [location, setLocation] = (0, import_react3.useState)(null);
1565
- const [error, setError] = (0, import_react3.useState)(null);
1566
- const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
1634
+ const [location, setLocation] = React.useState(null);
1635
+ const [error, setError] = React.useState(null);
1636
+ const [isLoading, setIsLoading] = React.useState(true);
1567
1637
  const config = {
1568
1638
  enableHighAccuracy: options.enableHighAccuracy ?? true,
1569
1639
  timeout: options.timeout ?? 15e3,
1570
1640
  maximumAge: options.maximumAge ?? 1e4
1571
1641
  };
1572
- const refreshLocation = (0, import_react3.useCallback)(async () => {
1642
+ const refreshLocation = React.useCallback(async () => {
1573
1643
  setIsLoading(true);
1574
1644
  setError(null);
1575
1645
  return new Promise((resolve) => {
1576
- import_geolocation.default.getCurrentPosition(
1646
+ Geolocation2__default.default.getCurrentPosition(
1577
1647
  (position) => {
1578
1648
  setLocation({
1579
1649
  latitude: position.coords.latitude,
@@ -1596,10 +1666,10 @@ function useLocation(options = {}) {
1596
1666
  );
1597
1667
  });
1598
1668
  }, [config.enableHighAccuracy, config.timeout, config.maximumAge]);
1599
- (0, import_react3.useEffect)(() => {
1669
+ React.useEffect(() => {
1600
1670
  refreshLocation();
1601
1671
  if (options.watchPosition) {
1602
- const watchId = import_geolocation.default.watchPosition(
1672
+ const watchId = Geolocation2__default.default.watchPosition(
1603
1673
  (position) => {
1604
1674
  setLocation({
1605
1675
  latitude: position.coords.latitude,
@@ -1617,7 +1687,7 @@ function useLocation(options = {}) {
1617
1687
  config
1618
1688
  );
1619
1689
  return () => {
1620
- import_geolocation.default.clearWatch(watchId);
1690
+ Geolocation2__default.default.clearWatch(watchId);
1621
1691
  };
1622
1692
  }
1623
1693
  return void 0;
@@ -1630,377 +1700,40 @@ function useLocation(options = {}) {
1630
1700
  };
1631
1701
  }
1632
1702
 
1633
- // src/hooks/usePassgageQRScanner.ts
1634
- function usePassgageQRScanner(options = {}) {
1635
- const { qrAccessService, deviceAccessService } = usePassgageAccess();
1636
- const { location } = useLocation();
1637
- const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
1638
- const [error, setError] = (0, import_react4.useState)(null);
1639
- const scan = (0, import_react4.useCallback)(
1640
- async (qrCode, device) => {
1641
- setIsLoading(true);
1642
- setError(null);
1643
- try {
1644
- let qrDevice = device;
1645
- if (!qrDevice) {
1646
- qrDevice = await deviceAccessService.findDeviceByQRCode(qrCode);
1647
- if (!qrDevice) {
1648
- throw new Error("QR device not found");
1649
- }
1650
- }
1651
- const result = await qrAccessService.validateQR({
1652
- qrCode,
1653
- device: qrDevice,
1654
- userLocation: location || void 0,
1655
- skipLocationCheck: options.skipLocationCheck,
1656
- skipRepetitiveCheck: options.skipRepetitiveCheck
1657
- });
1658
- if (!result.success) {
1659
- throw new Error(result.message);
1660
- }
1661
- options.onSuccess?.(result.entrance);
1662
- } catch (err) {
1663
- const error2 = err;
1664
- setError(error2);
1665
- options.onError?.(error2);
1666
- } finally {
1667
- setIsLoading(false);
1668
- }
1669
- },
1670
- [qrAccessService, deviceAccessService, location, options]
1671
- );
1672
- return {
1673
- scan,
1674
- isLoading,
1675
- error
1676
- };
1677
- }
1678
-
1679
- // src/hooks/usePassgageNFCScanner.ts
1680
- var import_react5 = require("react");
1681
- var import_react_native_nfc_manager = __toESM(require("react-native-nfc-manager"));
1682
- function reversedHexToDec(hexString) {
1683
- const hex = hexString.replace(/:/g, "");
1684
- return parseInt(hex, 16).toString();
1685
- }
1686
- function usePassgageNFCScanner(options = {}) {
1687
- const { nfcAccessService, deviceAccessService } = usePassgageAccess();
1688
- const { location } = useLocation();
1689
- const [isScanning, setIsScanning] = (0, import_react5.useState)(false);
1690
- const [error, setError] = (0, import_react5.useState)(null);
1691
- const stopScanning = (0, import_react5.useCallback)(async () => {
1692
- try {
1693
- await import_react_native_nfc_manager.default.cancelTechnologyRequest();
1694
- setIsScanning(false);
1695
- } catch {
1696
- }
1697
- }, []);
1698
- const handleNFCTag = (0, import_react5.useCallback)(
1699
- async (tag) => {
1700
- if (!tag.id) {
1701
- return;
1702
- }
1703
- try {
1704
- const nfcCode = reversedHexToDec(tag.id);
1705
- const device = await deviceAccessService.findDeviceByNFCCode(nfcCode);
1706
- if (!device) {
1707
- throw new Error("NFC device not found");
1708
- }
1709
- const result = await nfcAccessService.validateNFC({
1710
- nfcCode,
1711
- device,
1712
- userLocation: location || void 0,
1713
- skipLocationCheck: options.skipLocationCheck,
1714
- skipRepetitiveCheck: options.skipRepetitiveCheck
1715
- });
1716
- if (!result.success) {
1717
- throw new Error(result.message);
1718
- }
1719
- options.onSuccess?.(result.entrance);
1720
- await stopScanning();
1721
- } catch (err) {
1722
- const error2 = err;
1723
- setError(error2);
1724
- options.onError?.(error2);
1725
- await stopScanning();
1726
- }
1727
- },
1728
- [nfcAccessService, deviceAccessService, location, options, stopScanning]
1729
- );
1730
- const startScanning = (0, import_react5.useCallback)(async () => {
1731
- setIsScanning(true);
1732
- setError(null);
1733
- try {
1734
- await import_react_native_nfc_manager.default.requestTechnology(import_react_native_nfc_manager.NfcTech.Ndef, {
1735
- invalidateAfterFirstRead: true
1736
- });
1737
- const tag = await import_react_native_nfc_manager.default.getTag();
1738
- await handleNFCTag(tag || {});
1739
- } catch (err) {
1740
- const error2 = err;
1741
- setError(error2);
1742
- options.onError?.(error2);
1743
- setIsScanning(false);
1744
- }
1745
- }, [handleNFCTag, options]);
1746
- (0, import_react5.useEffect)(() => {
1747
- if (options.autoStart) {
1748
- startScanning();
1749
- }
1750
- return () => {
1751
- stopScanning();
1752
- };
1753
- }, [options.autoStart, startScanning, stopScanning]);
1754
- return {
1755
- startScanning,
1756
- stopScanning,
1757
- isScanning,
1758
- error
1759
- };
1760
- }
1761
-
1762
- // src/hooks/usePassgageCheckIn.ts
1763
- var import_react6 = require("react");
1764
- function usePassgageCheckIn(options = {}) {
1765
- const { checkInService } = usePassgageAccess();
1766
- const { location } = useLocation();
1767
- const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
1768
- const [error, setError] = (0, import_react6.useState)(null);
1769
- const getNearbyBranches = (0, import_react6.useCallback)(
1770
- async (params) => {
1771
- if (!location) {
1772
- return {
1773
- success: false,
1774
- error: "Location not available"
1775
- };
1776
- }
1777
- setIsLoading(true);
1778
- setError(null);
1779
- try {
1780
- const response = await checkInService.getNearbyBranches({
1781
- latitude: location.latitude,
1782
- longitude: location.longitude,
1783
- radius: params?.radius || options.radius
1784
- });
1785
- if (response.success && response.data) {
1786
- return {
1787
- success: true,
1788
- data: response.data
1789
- };
1790
- }
1791
- return {
1792
- success: false,
1793
- error: response.message || "Failed to fetch nearby branches"
1794
- };
1795
- } catch (err) {
1796
- const error2 = err;
1797
- setError(error2);
1798
- return {
1799
- success: false,
1800
- error: error2.message || "Failed to fetch nearby branches"
1801
- };
1802
- } finally {
1803
- setIsLoading(false);
1804
- }
1805
- },
1806
- [checkInService, location, options.radius]
1807
- );
1808
- const checkInEntry = (0, import_react6.useCallback)(
1809
- async (params) => {
1810
- setIsLoading(true);
1811
- setError(null);
1812
- try {
1813
- const result = await checkInService.checkIn({
1814
- branchId: params.branchId,
1815
- userId: params.userId,
1816
- entranceType: 0 /* ENTRY */,
1817
- userLocation: location || void 0
1818
- });
1819
- if (result.success) {
1820
- return {
1821
- success: true,
1822
- data: result.entrance
1823
- };
1824
- }
1825
- return {
1826
- success: false,
1827
- error: result.message || "Check-in failed"
1828
- };
1829
- } catch (err) {
1830
- const error2 = err;
1831
- setError(error2);
1832
- return {
1833
- success: false,
1834
- error: error2.message || "Check-in failed"
1835
- };
1836
- } finally {
1837
- setIsLoading(false);
1838
- }
1839
- },
1840
- [checkInService, location]
1841
- );
1842
- const checkInExit = (0, import_react6.useCallback)(
1843
- async (params) => {
1844
- setIsLoading(true);
1845
- setError(null);
1846
- try {
1847
- const result = await checkInService.checkIn({
1848
- branchId: params.branchId,
1849
- userId: params.userId,
1850
- entranceType: 1 /* EXIT */,
1851
- userLocation: location || void 0
1852
- });
1853
- if (result.success) {
1854
- return {
1855
- success: true,
1856
- data: result.entrance
1857
- };
1858
- }
1859
- return {
1860
- success: false,
1861
- error: result.message || "Check-out failed"
1862
- };
1863
- } catch (err) {
1864
- const error2 = err;
1865
- setError(error2);
1866
- return {
1867
- success: false,
1868
- error: error2.message || "Check-out failed"
1869
- };
1870
- } finally {
1871
- setIsLoading(false);
1872
- }
1873
- },
1874
- [checkInService, location]
1875
- );
1876
- return {
1877
- getNearbyBranches,
1878
- checkInEntry,
1879
- checkInExit,
1880
- isLoading,
1881
- error
1882
- };
1883
- }
1884
-
1885
- // src/hooks/usePassgageRemoteWork.ts
1886
- var import_react7 = require("react");
1887
- function usePassgageRemoteWork() {
1888
- const { remoteWorkService } = usePassgageAccess();
1889
- const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
1890
- const [error, setError] = (0, import_react7.useState)(null);
1891
- const logEntry = (0, import_react7.useCallback)(
1892
- async (params) => {
1893
- setIsLoading(true);
1894
- setError(null);
1895
- try {
1896
- const result = await remoteWorkService.logRemoteWork({
1897
- userId: params.userId,
1898
- entranceType: 0 /* ENTRY */,
1899
- timestamp: params.timestamp,
1900
- description: params.description
1901
- });
1902
- if (result.success) {
1903
- return {
1904
- success: true,
1905
- data: result.entrance
1906
- };
1907
- }
1908
- return {
1909
- success: false,
1910
- error: result.message || "Failed to log entry"
1911
- };
1912
- } catch (err) {
1913
- const error2 = err;
1914
- setError(error2);
1915
- return {
1916
- success: false,
1917
- error: error2.message || "Failed to log entry"
1918
- };
1919
- } finally {
1920
- setIsLoading(false);
1921
- }
1922
- },
1923
- [remoteWorkService]
1924
- );
1925
- const logExit = (0, import_react7.useCallback)(
1926
- async (params) => {
1927
- setIsLoading(true);
1928
- setError(null);
1929
- try {
1930
- const result = await remoteWorkService.logRemoteWork({
1931
- userId: params.userId,
1932
- entranceType: 1 /* EXIT */,
1933
- timestamp: params.timestamp,
1934
- description: params.description
1935
- });
1936
- if (result.success) {
1937
- return {
1938
- success: true,
1939
- data: result.entrance
1940
- };
1941
- }
1942
- return {
1943
- success: false,
1944
- error: result.message || "Failed to log exit"
1945
- };
1946
- } catch (err) {
1947
- const error2 = err;
1948
- setError(error2);
1949
- return {
1950
- success: false,
1951
- error: error2.message || "Failed to log exit"
1952
- };
1953
- } finally {
1954
- setIsLoading(false);
1955
- }
1956
- },
1957
- [remoteWorkService]
1958
- );
1959
- return {
1960
- logEntry,
1961
- logExit,
1962
- isLoading,
1963
- error
1964
- };
1965
- }
1966
-
1967
1703
  // src/index.ts
1968
1704
  var SDK_VERSION = "1.0.4";
1969
- // Annotate the CommonJS export names for ESM import in node:
1970
- 0 && (module.exports = {
1971
- ApiClient,
1972
- AuthService,
1973
- CheckInService,
1974
- DeviceAccessService,
1975
- DeviceDirection,
1976
- DeviceUsage,
1977
- Endpoints,
1978
- EntranceType,
1979
- LocationService,
1980
- NFCAccessService,
1981
- PassgageAccessProvider,
1982
- QRAccessService,
1983
- RemoteWorkService,
1984
- SDK_VERSION,
1985
- calculateDistance,
1986
- checkOnLocation,
1987
- checkRepetitiveRead,
1988
- clearReadRecords,
1989
- createApiClient,
1990
- formatDate,
1991
- formatDateTime,
1992
- formatISO,
1993
- formatTime,
1994
- parseISO,
1995
- useLocation,
1996
- usePassgageAccess,
1997
- usePassgageAuth,
1998
- usePassgageCheckIn,
1999
- usePassgageNFCScanner,
2000
- usePassgageQRScanner,
2001
- usePassgageRemoteWork,
2002
- validateCoordinates,
2003
- validateDeviceId,
2004
- validateNFCCode,
2005
- validateQRCode
2006
- });
1705
+
1706
+ exports.ApiClient = ApiClient;
1707
+ exports.AuthService = AuthService;
1708
+ exports.DeviceAccessService = DeviceAccessService;
1709
+ exports.DeviceDirection = DeviceDirection;
1710
+ exports.DeviceUsage = DeviceUsage;
1711
+ exports.Endpoints = endpoints_exports;
1712
+ exports.EntranceType = EntranceType;
1713
+ exports.LocationService = LocationService;
1714
+ exports.NfcAccessService = NfcAccessService;
1715
+ exports.PassgageAccessProvider = PassgageAccessProvider;
1716
+ exports.QRAccessService = QRAccessService;
1717
+ exports.SDK_VERSION = SDK_VERSION;
1718
+ exports.addQrReadRecord = addQrReadRecord;
1719
+ exports.calculateDistance = calculateDistance;
1720
+ exports.checkOnLocation = checkOnLocation;
1721
+ exports.checkRepetitiveRead = checkRepetitiveRead;
1722
+ exports.clearReadRecords = clearReadRecords;
1723
+ exports.createApiClient = createApiClient;
1724
+ exports.formatDate = formatDate;
1725
+ exports.formatDateTime = formatDateTime;
1726
+ exports.formatISO = formatISO;
1727
+ exports.formatTime = formatTime;
1728
+ exports.parseISO = parseISO;
1729
+ exports.reversedHexToDec = reversedHexToDec;
1730
+ exports.shouldValidateLocation = shouldValidateLocation;
1731
+ exports.useLocation = useLocation;
1732
+ exports.usePassgageAccessContext = usePassgageAccessContext;
1733
+ exports.usePassgageNFCScanner = usePassgageNFCScanner;
1734
+ exports.usePassgageQRScanner = usePassgageQRScanner;
1735
+ exports.validateCoordinates = validateCoordinates;
1736
+ exports.validateDeviceId = validateDeviceId;
1737
+ exports.validateLocation = validateLocation;
1738
+ exports.validateNFCCode = validateNFCCode;
1739
+ exports.validateQRCode = validateQRCode;