@passgage/sdk-react-native 1.0.1 → 1.0.3
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.d.mts +1049 -31
- package/dist/index.d.ts +1049 -31
- package/dist/index.js +1375 -90
- package/dist/index.mjs +1343 -87
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -27,24 +27,1199 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
|
-
// src/index.
|
|
30
|
+
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
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,
|
|
33
43
|
PassgageAccessProvider: () => PassgageAccessProvider,
|
|
44
|
+
QRAccessService: () => QRAccessService,
|
|
45
|
+
RemoteWorkService: () => RemoteWorkService,
|
|
34
46
|
SDK_VERSION: () => SDK_VERSION,
|
|
35
|
-
|
|
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,
|
|
36
57
|
useLocation: () => useLocation,
|
|
37
|
-
useNFCScanner: () => useNFCScanner,
|
|
38
58
|
usePassgageAccess: () => usePassgageAccess,
|
|
39
59
|
usePassgageAuth: () => usePassgageAuth,
|
|
40
|
-
|
|
41
|
-
|
|
60
|
+
usePassgageCheckIn: () => usePassgageCheckIn,
|
|
61
|
+
usePassgageNFCScanner: () => usePassgageNFCScanner,
|
|
62
|
+
usePassgageQRScanner: () => usePassgageQRScanner,
|
|
63
|
+
usePassgageRemoteWork: () => usePassgageRemoteWork,
|
|
64
|
+
validateCoordinates: () => validateCoordinates,
|
|
65
|
+
validateDeviceId: () => validateDeviceId,
|
|
66
|
+
validateNFCCode: () => validateNFCCode,
|
|
67
|
+
validateQRCode: () => validateQRCode
|
|
42
68
|
});
|
|
43
69
|
module.exports = __toCommonJS(index_exports);
|
|
44
70
|
|
|
71
|
+
// src/api/client.ts
|
|
72
|
+
var import_axios = __toESM(require("axios"));
|
|
73
|
+
var ApiClient = class {
|
|
74
|
+
constructor(config) {
|
|
75
|
+
this.isRefreshing = false;
|
|
76
|
+
this.refreshQueue = [];
|
|
77
|
+
this.config = {
|
|
78
|
+
timeout: 3e4,
|
|
79
|
+
apiVersion: "v2",
|
|
80
|
+
...config
|
|
81
|
+
};
|
|
82
|
+
this.axiosInstance = import_axios.default.create({
|
|
83
|
+
baseURL: `${this.config.baseURL}/api/${this.config.apiVersion}`,
|
|
84
|
+
timeout: this.config.timeout,
|
|
85
|
+
headers: {
|
|
86
|
+
"Content-Type": "application/json",
|
|
87
|
+
Accept: "application/json",
|
|
88
|
+
...this.config.headers
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
this.setupInterceptors();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Setup request and response interceptors
|
|
95
|
+
*/
|
|
96
|
+
setupInterceptors() {
|
|
97
|
+
this.axiosInstance.interceptors.request.use(
|
|
98
|
+
(config) => {
|
|
99
|
+
const skipAuth = config.skipAuth;
|
|
100
|
+
if (this.config.token && !skipAuth) {
|
|
101
|
+
config.headers.Authorization = `Bearer ${this.config.token}`;
|
|
102
|
+
}
|
|
103
|
+
return config;
|
|
104
|
+
},
|
|
105
|
+
(error) => {
|
|
106
|
+
return Promise.reject(this.handleError(error));
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
this.axiosInstance.interceptors.response.use(
|
|
110
|
+
(response) => response,
|
|
111
|
+
async (error) => {
|
|
112
|
+
const originalRequest = error.config;
|
|
113
|
+
if (error.response?.status === 401 && originalRequest && !originalRequest._retry) {
|
|
114
|
+
const skipAuth = originalRequest.skipAuth;
|
|
115
|
+
if (skipAuth) {
|
|
116
|
+
return Promise.reject(this.handleError(error));
|
|
117
|
+
}
|
|
118
|
+
if (this.config.onTokenRefreshNeeded) {
|
|
119
|
+
originalRequest._retry = true;
|
|
120
|
+
const retryOriginalRequest = new Promise((resolve, reject) => {
|
|
121
|
+
this.refreshQueue.push({
|
|
122
|
+
config: originalRequest,
|
|
123
|
+
resolve,
|
|
124
|
+
reject
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
if (!this.isRefreshing) {
|
|
128
|
+
this.isRefreshing = true;
|
|
129
|
+
try {
|
|
130
|
+
const newToken = await this.config.onTokenRefreshNeeded();
|
|
131
|
+
if (newToken) {
|
|
132
|
+
this.setToken(newToken);
|
|
133
|
+
this.refreshQueue.forEach(({ config, resolve, reject }) => {
|
|
134
|
+
if (config.headers) {
|
|
135
|
+
config.headers.Authorization = `Bearer ${newToken}`;
|
|
136
|
+
}
|
|
137
|
+
this.axiosInstance.request(config).then(resolve).catch(reject);
|
|
138
|
+
});
|
|
139
|
+
this.refreshQueue = [];
|
|
140
|
+
} else {
|
|
141
|
+
this.refreshQueue.forEach(({ reject }) => {
|
|
142
|
+
reject(new Error("Token refresh failed"));
|
|
143
|
+
});
|
|
144
|
+
this.refreshQueue = [];
|
|
145
|
+
if (this.config.onUnauthorized) {
|
|
146
|
+
this.config.onUnauthorized();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
} catch (refreshError) {
|
|
150
|
+
this.refreshQueue.forEach(({ reject }) => {
|
|
151
|
+
reject(refreshError);
|
|
152
|
+
});
|
|
153
|
+
this.refreshQueue = [];
|
|
154
|
+
if (this.config.onUnauthorized) {
|
|
155
|
+
this.config.onUnauthorized();
|
|
156
|
+
}
|
|
157
|
+
} finally {
|
|
158
|
+
this.isRefreshing = false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return retryOriginalRequest;
|
|
162
|
+
} else {
|
|
163
|
+
if (this.config.onUnauthorized) {
|
|
164
|
+
this.config.onUnauthorized();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const apiError = this.handleError(error);
|
|
169
|
+
if (this.config.onError) {
|
|
170
|
+
this.config.onError(apiError);
|
|
171
|
+
}
|
|
172
|
+
return Promise.reject(apiError);
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Handle API errors
|
|
178
|
+
*/
|
|
179
|
+
handleError(error) {
|
|
180
|
+
const responseData = error.response?.data;
|
|
181
|
+
const apiError = new Error(
|
|
182
|
+
responseData?.message || error.message || "An unknown error occurred"
|
|
183
|
+
);
|
|
184
|
+
apiError.code = error.code;
|
|
185
|
+
apiError.status = error.response?.status;
|
|
186
|
+
apiError.response = responseData;
|
|
187
|
+
return apiError;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Update authorization token
|
|
191
|
+
*/
|
|
192
|
+
setToken(token) {
|
|
193
|
+
this.config.token = token || void 0;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Remove authorization token
|
|
197
|
+
*/
|
|
198
|
+
clearToken() {
|
|
199
|
+
this.config.token = void 0;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Generic GET request
|
|
203
|
+
*/
|
|
204
|
+
async get(options) {
|
|
205
|
+
const response = await this.axiosInstance.get(options.endpoint, {
|
|
206
|
+
params: options.params,
|
|
207
|
+
headers: options.headers,
|
|
208
|
+
...options.config,
|
|
209
|
+
skipAuth: options.skipAuth
|
|
210
|
+
});
|
|
211
|
+
return response.data;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Generic POST request
|
|
215
|
+
*/
|
|
216
|
+
async post(options) {
|
|
217
|
+
const response = await this.axiosInstance.post(
|
|
218
|
+
options.endpoint,
|
|
219
|
+
options.data,
|
|
220
|
+
{
|
|
221
|
+
params: options.params,
|
|
222
|
+
headers: options.headers,
|
|
223
|
+
...options.config,
|
|
224
|
+
skipAuth: options.skipAuth
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
return response.data;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Generic PUT request
|
|
231
|
+
*/
|
|
232
|
+
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
|
+
);
|
|
243
|
+
return response.data;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Generic PATCH request
|
|
247
|
+
*/
|
|
248
|
+
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
|
+
);
|
|
259
|
+
return response.data;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Generic DELETE request
|
|
263
|
+
*/
|
|
264
|
+
async delete(options) {
|
|
265
|
+
const response = await this.axiosInstance.delete(options.endpoint, {
|
|
266
|
+
params: options.params,
|
|
267
|
+
headers: options.headers,
|
|
268
|
+
...options.config,
|
|
269
|
+
skipAuth: options.skipAuth
|
|
270
|
+
});
|
|
271
|
+
return response.data;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
function createApiClient(config) {
|
|
275
|
+
return new ApiClient(config);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/api/endpoints.ts
|
|
279
|
+
var endpoints_exports = {};
|
|
280
|
+
__export(endpoints_exports, {
|
|
281
|
+
EP_BRANCHES: () => EP_BRANCHES,
|
|
282
|
+
EP_CREATE_QR: () => EP_CREATE_QR,
|
|
283
|
+
EP_DEVICES: () => EP_DEVICES,
|
|
284
|
+
EP_ENTRANCES: () => EP_ENTRANCES,
|
|
285
|
+
EP_LOCATION_VERIFICATION: () => EP_LOCATION_VERIFICATION,
|
|
286
|
+
EP_LOGIN: () => EP_LOGIN,
|
|
287
|
+
EP_ME: () => EP_ME,
|
|
288
|
+
EP_NFC_CHECK: () => EP_NFC_CHECK,
|
|
289
|
+
EP_QR_ACCESS: () => EP_QR_ACCESS,
|
|
290
|
+
EP_QR_CHECK: () => EP_QR_CHECK,
|
|
291
|
+
EP_QR_DEVICES: () => EP_QR_DEVICES,
|
|
292
|
+
EP_TOKEN: () => EP_TOKEN,
|
|
293
|
+
EP_TRIGGER_IOT: () => EP_TRIGGER_IOT,
|
|
294
|
+
EP_USERS: () => EP_USERS
|
|
295
|
+
});
|
|
296
|
+
var EP_LOGIN = "users/sign_in";
|
|
297
|
+
var EP_TOKEN = "token";
|
|
298
|
+
var EP_DEVICES = "devices";
|
|
299
|
+
var EP_QR_DEVICES = "devices/qr_devices";
|
|
300
|
+
var EP_QR_ACCESS = "qr_access/accessible_qrs";
|
|
301
|
+
var EP_QR_CHECK = "qr_check";
|
|
302
|
+
var EP_NFC_CHECK = "nfc_check";
|
|
303
|
+
var EP_ENTRANCES = "entrances";
|
|
304
|
+
var EP_CREATE_QR = "entrances/create_from_qr";
|
|
305
|
+
var EP_BRANCHES = "branches";
|
|
306
|
+
var EP_LOCATION_VERIFICATION = "location_verification_logs";
|
|
307
|
+
var EP_TRIGGER_IOT = "iot/trigger";
|
|
308
|
+
var EP_USERS = "users";
|
|
309
|
+
var EP_ME = "users/lite_me";
|
|
310
|
+
|
|
311
|
+
// src/models/common.ts
|
|
312
|
+
var EntranceType = /* @__PURE__ */ ((EntranceType2) => {
|
|
313
|
+
EntranceType2[EntranceType2["ENTRY"] = 0] = "ENTRY";
|
|
314
|
+
EntranceType2[EntranceType2["EXIT"] = 1] = "EXIT";
|
|
315
|
+
return EntranceType2;
|
|
316
|
+
})(EntranceType || {});
|
|
317
|
+
var DeviceUsage = /* @__PURE__ */ ((DeviceUsage2) => {
|
|
318
|
+
DeviceUsage2["PDKS"] = "pdks";
|
|
319
|
+
DeviceUsage2["MEETING_ROOM"] = "meeting_room";
|
|
320
|
+
DeviceUsage2["FOOD"] = "food";
|
|
321
|
+
return DeviceUsage2;
|
|
322
|
+
})(DeviceUsage || {});
|
|
323
|
+
var DeviceDirection = /* @__PURE__ */ ((DeviceDirection2) => {
|
|
324
|
+
DeviceDirection2[DeviceDirection2["ENTRY"] = 0] = "ENTRY";
|
|
325
|
+
DeviceDirection2[DeviceDirection2["EXIT"] = 1] = "EXIT";
|
|
326
|
+
DeviceDirection2[DeviceDirection2["BIDIRECTIONAL"] = 2] = "BIDIRECTIONAL";
|
|
327
|
+
return DeviceDirection2;
|
|
328
|
+
})(DeviceDirection || {});
|
|
329
|
+
|
|
330
|
+
// 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
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Login with credentials
|
|
344
|
+
*
|
|
345
|
+
* @param credentials - User login credentials (email/phone and password)
|
|
346
|
+
* @returns Login result with tokens on success
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```typescript
|
|
350
|
+
* const result = await authService.login({
|
|
351
|
+
* login: 'user@example.com',
|
|
352
|
+
* password: 'password123'
|
|
353
|
+
* });
|
|
354
|
+
*
|
|
355
|
+
* if (result.success) {
|
|
356
|
+
* console.log('Access token:', result.tokens.access.token);
|
|
357
|
+
* } else {
|
|
358
|
+
* console.error('Login failed:', result.error);
|
|
359
|
+
* }
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
async login(credentials) {
|
|
363
|
+
try {
|
|
364
|
+
const requestBody = {
|
|
365
|
+
user: {
|
|
366
|
+
login: credentials.login,
|
|
367
|
+
password: credentials.password
|
|
368
|
+
}
|
|
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
|
+
});
|
|
376
|
+
if (!response.success || !response.data?.tokens) {
|
|
377
|
+
return {
|
|
378
|
+
success: false,
|
|
379
|
+
error: response.message || "Login failed",
|
|
380
|
+
code: "LOGIN_FAILED"
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
const tokens = response.data.tokens;
|
|
384
|
+
if (this.tokenStorage) {
|
|
385
|
+
await this.tokenStorage.saveTokens(tokens);
|
|
386
|
+
}
|
|
387
|
+
this.apiClient.setToken(tokens.access.token);
|
|
388
|
+
let user;
|
|
389
|
+
try {
|
|
390
|
+
const userResult = await this.getCurrentUser();
|
|
391
|
+
if (userResult.success) {
|
|
392
|
+
user = userResult.user;
|
|
393
|
+
if (this.tokenStorage) {
|
|
394
|
+
await this.tokenStorage.saveUser(user);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.warn("Failed to fetch user info after login:", error);
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
success: true,
|
|
402
|
+
tokens,
|
|
403
|
+
user
|
|
404
|
+
};
|
|
405
|
+
} catch (error) {
|
|
406
|
+
return {
|
|
407
|
+
success: false,
|
|
408
|
+
error: error.message || "An error occurred during login",
|
|
409
|
+
code: error.code || "NETWORK_ERROR"
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Refresh access token using refresh token
|
|
415
|
+
*
|
|
416
|
+
* @param refreshToken - The refresh token
|
|
417
|
+
* @returns Refresh result with new tokens on success
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```typescript
|
|
421
|
+
* const result = await authService.refreshToken('refresh_token_here');
|
|
422
|
+
*
|
|
423
|
+
* if (result.success) {
|
|
424
|
+
* console.log('New access token:', result.tokens.access.token);
|
|
425
|
+
* }
|
|
426
|
+
* ```
|
|
427
|
+
*/
|
|
428
|
+
async refreshToken(refreshToken) {
|
|
429
|
+
try {
|
|
430
|
+
const requestBody = {
|
|
431
|
+
refresh_token: refreshToken
|
|
432
|
+
};
|
|
433
|
+
const response = await this.apiClient.post({
|
|
434
|
+
endpoint: "/token",
|
|
435
|
+
data: requestBody,
|
|
436
|
+
skipAuth: true
|
|
437
|
+
});
|
|
438
|
+
if (!response.success || !response.data?.token || !response.data?.refresh_token) {
|
|
439
|
+
return {
|
|
440
|
+
success: false,
|
|
441
|
+
error: response.message || "Token refresh failed",
|
|
442
|
+
code: "REFRESH_FAILED"
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
const tokens = {
|
|
446
|
+
access: {
|
|
447
|
+
token: response.data.token,
|
|
448
|
+
expiresIn: "30 days"
|
|
449
|
+
},
|
|
450
|
+
refresh: {
|
|
451
|
+
token: response.data.refresh_token,
|
|
452
|
+
expiresIn: "30 days"
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
if (this.tokenStorage) {
|
|
456
|
+
await this.tokenStorage.saveTokens(tokens);
|
|
457
|
+
}
|
|
458
|
+
this.apiClient.setToken(tokens.access.token);
|
|
459
|
+
return {
|
|
460
|
+
success: true,
|
|
461
|
+
tokens
|
|
462
|
+
};
|
|
463
|
+
} catch (error) {
|
|
464
|
+
return {
|
|
465
|
+
success: false,
|
|
466
|
+
error: error.message || "An error occurred during token refresh",
|
|
467
|
+
code: error.code || "NETWORK_ERROR"
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Get current user information
|
|
473
|
+
*
|
|
474
|
+
* @returns Result with user information
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* ```typescript
|
|
478
|
+
* const result = await authService.getCurrentUser();
|
|
479
|
+
*
|
|
480
|
+
* if (result.success) {
|
|
481
|
+
* console.log('User name:', result.user.fullName);
|
|
482
|
+
* }
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
async getCurrentUser() {
|
|
486
|
+
try {
|
|
487
|
+
const response = await this.apiClient.get({
|
|
488
|
+
endpoint: "/api/v2/users/me"
|
|
489
|
+
});
|
|
490
|
+
if (!response.success || !response.data) {
|
|
491
|
+
return {
|
|
492
|
+
success: false,
|
|
493
|
+
error: response.message || "Failed to fetch user information"
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
const userData = response.data;
|
|
497
|
+
const user = {
|
|
498
|
+
id: userData.id,
|
|
499
|
+
email: userData.email,
|
|
500
|
+
firstName: userData.first_name,
|
|
501
|
+
lastName: userData.last_name,
|
|
502
|
+
company: {
|
|
503
|
+
id: userData.company.id,
|
|
504
|
+
name: userData.company.name
|
|
505
|
+
},
|
|
506
|
+
fullName: userData.full_name || `${userData.first_name} ${userData.last_name}`,
|
|
507
|
+
gsm: userData.gsm,
|
|
508
|
+
avatar: userData.avatar?.url,
|
|
509
|
+
jobTitle: userData.job_title,
|
|
510
|
+
birthDate: userData.birth_date,
|
|
511
|
+
cardNo: userData.card_no
|
|
512
|
+
};
|
|
513
|
+
return {
|
|
514
|
+
success: true,
|
|
515
|
+
user
|
|
516
|
+
};
|
|
517
|
+
} catch (error) {
|
|
518
|
+
return {
|
|
519
|
+
success: false,
|
|
520
|
+
error: error.message || "Failed to fetch user information"
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
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
|
|
557
|
+
*/
|
|
558
|
+
async getStoredTokens() {
|
|
559
|
+
if (!this.tokenStorage) {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
return await this.tokenStorage.getTokens();
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Get stored user
|
|
566
|
+
*
|
|
567
|
+
* @returns Stored user or null
|
|
568
|
+
*/
|
|
569
|
+
async getStoredUser() {
|
|
570
|
+
if (!this.tokenStorage) {
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
return await this.tokenStorage.getUser();
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
// src/utils/location.ts
|
|
578
|
+
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);
|
|
585
|
+
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
586
|
+
return R * c;
|
|
587
|
+
}
|
|
588
|
+
function checkOnLocation(targetLat, targetLon, allowedRange, userPosition) {
|
|
589
|
+
if (!userPosition) {
|
|
590
|
+
return { ok: false };
|
|
591
|
+
}
|
|
592
|
+
const distance = calculateDistance(
|
|
593
|
+
targetLat,
|
|
594
|
+
targetLon,
|
|
595
|
+
userPosition.latitude,
|
|
596
|
+
userPosition.longitude
|
|
597
|
+
);
|
|
598
|
+
return {
|
|
599
|
+
ok: distance <= allowedRange,
|
|
600
|
+
distance
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
function validateCoordinates(coords) {
|
|
604
|
+
if (!coords) {
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
const { latitude, longitude } = coords;
|
|
608
|
+
return typeof latitude === "number" && typeof longitude === "number" && latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// src/utils/validation.ts
|
|
612
|
+
var READ_TIMEOUT = 15e3;
|
|
613
|
+
var readRecords = [];
|
|
614
|
+
function checkRepetitiveRead(code) {
|
|
615
|
+
const now = Date.now();
|
|
616
|
+
readRecords = readRecords.filter((record) => now - record.timestamp < READ_TIMEOUT);
|
|
617
|
+
const recentRead = readRecords.find(
|
|
618
|
+
(record) => record.code === code && now - record.timestamp < READ_TIMEOUT
|
|
619
|
+
);
|
|
620
|
+
if (recentRead) {
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
readRecords.push({ code, timestamp: now });
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
function clearReadRecords() {
|
|
627
|
+
readRecords = [];
|
|
628
|
+
}
|
|
629
|
+
function validateQRCode(code) {
|
|
630
|
+
return typeof code === "string" && code.length > 0;
|
|
631
|
+
}
|
|
632
|
+
function validateNFCCode(code) {
|
|
633
|
+
return typeof code === "string" && code.length > 0;
|
|
634
|
+
}
|
|
635
|
+
function validateDeviceId(id) {
|
|
636
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
637
|
+
return uuidRegex.test(id);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/utils/date.ts
|
|
641
|
+
function formatISO(date = /* @__PURE__ */ new Date()) {
|
|
642
|
+
return date.toISOString();
|
|
643
|
+
}
|
|
644
|
+
function formatDate(date = /* @__PURE__ */ new Date()) {
|
|
645
|
+
const year = date.getFullYear();
|
|
646
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
647
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
648
|
+
return `${year}-${month}-${day}`;
|
|
649
|
+
}
|
|
650
|
+
function formatTime(date = /* @__PURE__ */ new Date()) {
|
|
651
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
652
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
653
|
+
return `${hours}:${minutes}`;
|
|
654
|
+
}
|
|
655
|
+
function formatDateTime(date = /* @__PURE__ */ new Date()) {
|
|
656
|
+
const dateStr = formatDate(date);
|
|
657
|
+
const timeStr = formatTime(date);
|
|
658
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
659
|
+
return `${dateStr} ${timeStr}:${seconds}`;
|
|
660
|
+
}
|
|
661
|
+
function parseISO(isoString) {
|
|
662
|
+
return new Date(isoString);
|
|
663
|
+
}
|
|
664
|
+
|
|
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)) {
|
|
687
|
+
return { valid: true };
|
|
688
|
+
}
|
|
689
|
+
if (!userLocation) {
|
|
690
|
+
return { valid: false };
|
|
691
|
+
}
|
|
692
|
+
const locationCheck = checkOnLocation(
|
|
693
|
+
device.latitude,
|
|
694
|
+
device.longitude,
|
|
695
|
+
device.range || 100,
|
|
696
|
+
userLocation
|
|
697
|
+
);
|
|
698
|
+
return {
|
|
699
|
+
valid: locationCheck.ok,
|
|
700
|
+
distance: locationCheck.distance
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Validate QR code with full checks
|
|
705
|
+
*/
|
|
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) {
|
|
725
|
+
return {
|
|
726
|
+
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
|
+
}
|
|
732
|
+
};
|
|
733
|
+
}
|
|
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) {
|
|
741
|
+
return {
|
|
742
|
+
success: false,
|
|
743
|
+
message: response.message || "QR validation failed",
|
|
744
|
+
error: { code: "API_ERROR" }
|
|
745
|
+
};
|
|
746
|
+
}
|
|
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
|
+
}
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Create entrance from QR code
|
|
762
|
+
*/
|
|
763
|
+
async createEntranceFromQR(request) {
|
|
764
|
+
return this.apiClient.post({
|
|
765
|
+
endpoint: EP_CREATE_QR,
|
|
766
|
+
data: request
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Trigger IoT device
|
|
771
|
+
*/
|
|
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
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Validate NFC code format
|
|
786
|
+
*/
|
|
787
|
+
validateNFCFormat(code) {
|
|
788
|
+
return validateNFCCode(code);
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Check if location validation is required
|
|
792
|
+
*/
|
|
793
|
+
shouldValidateLocation(device) {
|
|
794
|
+
return device.nfc_range_matter === "1" && !!device.latitude && !!device.longitude;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Validate user location against device location
|
|
798
|
+
*/
|
|
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 }
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Get device by ID
|
|
1089
|
+
*/
|
|
1090
|
+
async getDeviceById(deviceId) {
|
|
1091
|
+
return this.apiClient.get({
|
|
1092
|
+
endpoint: `${EP_DEVICES}/${deviceId}`
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Check if user has access to a device
|
|
1097
|
+
*/
|
|
1098
|
+
async checkDeviceAccess(deviceId) {
|
|
1099
|
+
try {
|
|
1100
|
+
const response = await this.getAccessibleQRs();
|
|
1101
|
+
if (!response.success || !response.data) {
|
|
1102
|
+
return false;
|
|
1103
|
+
}
|
|
1104
|
+
return response.data.qr_ids.includes(deviceId);
|
|
1105
|
+
} catch {
|
|
1106
|
+
return false;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Find QR device by QR code ID
|
|
1111
|
+
*/
|
|
1112
|
+
async findDeviceByQRCode(qrCodeId) {
|
|
1113
|
+
try {
|
|
1114
|
+
const devices = await this.getAllQRDevices();
|
|
1115
|
+
return devices.find((device) => device.qr_code_id === qrCodeId);
|
|
1116
|
+
} catch {
|
|
1117
|
+
return void 0;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
/**
|
|
1121
|
+
* Find QR device by NFC code
|
|
1122
|
+
*/
|
|
1123
|
+
async findDeviceByNFCCode(nfcCode) {
|
|
1124
|
+
try {
|
|
1125
|
+
const devices = await this.getAllQRDevices();
|
|
1126
|
+
return devices.find((device) => device.nfc_code === nfcCode);
|
|
1127
|
+
} catch {
|
|
1128
|
+
return void 0;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
// src/services/LocationService.ts
|
|
1134
|
+
var LocationService = class {
|
|
1135
|
+
constructor(apiClient) {
|
|
1136
|
+
this.apiClient = apiClient;
|
|
1137
|
+
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Log location verification
|
|
1140
|
+
*/
|
|
1141
|
+
async logLocationVerification(log) {
|
|
1142
|
+
return this.apiClient.post({
|
|
1143
|
+
endpoint: EP_LOCATION_VERIFICATION,
|
|
1144
|
+
data: { log }
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* Create location verification log for QR scan
|
|
1149
|
+
*/
|
|
1150
|
+
async logQRScan(params) {
|
|
1151
|
+
const log = {
|
|
1152
|
+
mobileLatitude: params.mobileLocation.latitude,
|
|
1153
|
+
mobileLongitude: params.mobileLocation.longitude,
|
|
1154
|
+
accuracy: params.mobileLocation.accuracy,
|
|
1155
|
+
altitude: params.mobileLocation.altitude,
|
|
1156
|
+
qrLatitude: params.qrLocation?.latitude ?? -1,
|
|
1157
|
+
qrLongitude: params.qrLocation?.longitude ?? -1,
|
|
1158
|
+
currentScreen: params.currentScreen,
|
|
1159
|
+
qr: params.qrCode,
|
|
1160
|
+
errorCode: params.errorCode,
|
|
1161
|
+
message: params.message,
|
|
1162
|
+
navigation_step: "qr_scan_location",
|
|
1163
|
+
isGps: true,
|
|
1164
|
+
deviceRange: params.deviceRange || 0,
|
|
1165
|
+
distance: params.distance,
|
|
1166
|
+
additionalInfo: params.additionalInfo || "",
|
|
1167
|
+
customData: params.customData
|
|
1168
|
+
};
|
|
1169
|
+
return this.logLocationVerification(log);
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Create location verification log for NFC scan
|
|
1173
|
+
*/
|
|
1174
|
+
async logNFCScan(params) {
|
|
1175
|
+
const log = {
|
|
1176
|
+
mobileLatitude: params.mobileLocation.latitude,
|
|
1177
|
+
mobileLongitude: params.mobileLocation.longitude,
|
|
1178
|
+
accuracy: params.mobileLocation.accuracy,
|
|
1179
|
+
altitude: params.mobileLocation.altitude,
|
|
1180
|
+
qrLatitude: params.nfcLocation?.latitude ?? -1,
|
|
1181
|
+
qrLongitude: params.nfcLocation?.longitude ?? -1,
|
|
1182
|
+
currentScreen: params.currentScreen,
|
|
1183
|
+
qr: params.nfcCode,
|
|
1184
|
+
errorCode: params.errorCode,
|
|
1185
|
+
message: params.message,
|
|
1186
|
+
navigation_step: "nfc_scan_location",
|
|
1187
|
+
isGps: true,
|
|
1188
|
+
deviceRange: params.deviceRange || 0,
|
|
1189
|
+
distance: params.distance,
|
|
1190
|
+
additionalInfo: params.additionalInfo || "",
|
|
1191
|
+
customData: params.customData
|
|
1192
|
+
};
|
|
1193
|
+
return this.logLocationVerification(log);
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Create location verification log for check-in
|
|
1197
|
+
*/
|
|
1198
|
+
async logCheckIn(params) {
|
|
1199
|
+
const log = {
|
|
1200
|
+
mobileLatitude: params.mobileLocation.latitude,
|
|
1201
|
+
mobileLongitude: params.mobileLocation.longitude,
|
|
1202
|
+
accuracy: params.mobileLocation.accuracy,
|
|
1203
|
+
altitude: params.mobileLocation.altitude,
|
|
1204
|
+
qrLatitude: params.branchLocation?.latitude ?? -1,
|
|
1205
|
+
qrLongitude: params.branchLocation?.longitude ?? -1,
|
|
1206
|
+
currentScreen: params.currentScreen,
|
|
1207
|
+
qr: "-",
|
|
1208
|
+
errorCode: params.errorCode,
|
|
1209
|
+
message: params.message,
|
|
1210
|
+
navigation_step: "check_in",
|
|
1211
|
+
isGps: true,
|
|
1212
|
+
deviceRange: 0,
|
|
1213
|
+
distance: params.distance,
|
|
1214
|
+
additionalInfo: params.additionalInfo || "buraday\u0131m",
|
|
1215
|
+
customData: params.customData
|
|
1216
|
+
};
|
|
1217
|
+
return this.logLocationVerification(log);
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
|
|
45
1221
|
// src/providers/PassgageAccessProvider.tsx
|
|
46
1222
|
var import_react = __toESM(require("react"));
|
|
47
|
-
var import_sdk_core = require("@passgage/sdk-core");
|
|
48
1223
|
|
|
49
1224
|
// src/utils/secureStorage.ts
|
|
50
1225
|
var Keychain = __toESM(require("react-native-keychain"));
|
|
@@ -183,7 +1358,7 @@ function PassgageAccessProvider({
|
|
|
183
1358
|
const { apiClient, services } = (0, import_react.useMemo)(() => {
|
|
184
1359
|
const secureStorage = createSecureStorage();
|
|
185
1360
|
let authService;
|
|
186
|
-
const client =
|
|
1361
|
+
const client = createApiClient({
|
|
187
1362
|
baseURL: config.baseURL,
|
|
188
1363
|
token: config.token,
|
|
189
1364
|
apiVersion: config.apiVersion,
|
|
@@ -202,16 +1377,16 @@ function PassgageAccessProvider({
|
|
|
202
1377
|
return null;
|
|
203
1378
|
}
|
|
204
1379
|
});
|
|
205
|
-
authService = new
|
|
1380
|
+
authService = new AuthService(client);
|
|
206
1381
|
authService.setTokenStorage(secureStorage);
|
|
207
1382
|
const allServices = {
|
|
208
1383
|
authService,
|
|
209
|
-
qrAccessService: new
|
|
210
|
-
nfcAccessService: new
|
|
211
|
-
checkInService: new
|
|
212
|
-
remoteWorkService: new
|
|
213
|
-
deviceAccessService: new
|
|
214
|
-
locationService: new
|
|
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)
|
|
215
1390
|
};
|
|
216
1391
|
return {
|
|
217
1392
|
apiClient: client,
|
|
@@ -379,7 +1554,7 @@ function usePassgageAuth(options = {}) {
|
|
|
379
1554
|
};
|
|
380
1555
|
}
|
|
381
1556
|
|
|
382
|
-
// src/hooks/
|
|
1557
|
+
// src/hooks/usePassgageQRScanner.ts
|
|
383
1558
|
var import_react4 = require("react");
|
|
384
1559
|
|
|
385
1560
|
// src/hooks/useLocation.ts
|
|
@@ -455,8 +1630,8 @@ function useLocation(options = {}) {
|
|
|
455
1630
|
};
|
|
456
1631
|
}
|
|
457
1632
|
|
|
458
|
-
// src/hooks/
|
|
459
|
-
function
|
|
1633
|
+
// src/hooks/usePassgageQRScanner.ts
|
|
1634
|
+
function usePassgageQRScanner(options = {}) {
|
|
460
1635
|
const { qrAccessService, deviceAccessService } = usePassgageAccess();
|
|
461
1636
|
const { location } = useLocation();
|
|
462
1637
|
const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
|
|
@@ -501,14 +1676,14 @@ function useQRScanner(options = {}) {
|
|
|
501
1676
|
};
|
|
502
1677
|
}
|
|
503
1678
|
|
|
504
|
-
// src/hooks/
|
|
1679
|
+
// src/hooks/usePassgageNFCScanner.ts
|
|
505
1680
|
var import_react5 = require("react");
|
|
506
1681
|
var import_react_native_nfc_manager = __toESM(require("react-native-nfc-manager"));
|
|
507
1682
|
function reversedHexToDec(hexString) {
|
|
508
1683
|
const hex = hexString.replace(/:/g, "");
|
|
509
1684
|
return parseInt(hex, 16).toString();
|
|
510
1685
|
}
|
|
511
|
-
function
|
|
1686
|
+
function usePassgageNFCScanner(options = {}) {
|
|
512
1687
|
const { nfcAccessService, deviceAccessService } = usePassgageAccess();
|
|
513
1688
|
const { location } = useLocation();
|
|
514
1689
|
const [isScanning, setIsScanning] = (0, import_react5.useState)(false);
|
|
@@ -584,138 +1759,248 @@ function useNFCScanner(options = {}) {
|
|
|
584
1759
|
};
|
|
585
1760
|
}
|
|
586
1761
|
|
|
587
|
-
// src/hooks/
|
|
1762
|
+
// src/hooks/usePassgageCheckIn.ts
|
|
588
1763
|
var import_react6 = require("react");
|
|
589
|
-
function
|
|
590
|
-
const { checkInService
|
|
1764
|
+
function usePassgageCheckIn(options = {}) {
|
|
1765
|
+
const { checkInService } = usePassgageAccess();
|
|
591
1766
|
const { location } = useLocation();
|
|
592
|
-
const [nearbyBranches, setNearbyBranches] = (0, import_react6.useState)([]);
|
|
593
1767
|
const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
|
|
594
1768
|
const [error, setError] = (0, import_react6.useState)(null);
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
const response = await checkInService.getNearbyBranches({
|
|
603
|
-
latitude: location.latitude,
|
|
604
|
-
longitude: location.longitude,
|
|
605
|
-
radius: options.radius
|
|
606
|
-
});
|
|
607
|
-
if (response.success && response.data) {
|
|
608
|
-
setNearbyBranches(response.data);
|
|
1769
|
+
const getNearbyBranches = (0, import_react6.useCallback)(
|
|
1770
|
+
async (params) => {
|
|
1771
|
+
if (!location) {
|
|
1772
|
+
return {
|
|
1773
|
+
success: false,
|
|
1774
|
+
error: "Location not available"
|
|
1775
|
+
};
|
|
609
1776
|
}
|
|
610
|
-
|
|
611
|
-
setError(
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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)(
|
|
617
1809
|
async (params) => {
|
|
618
1810
|
setIsLoading(true);
|
|
619
1811
|
setError(null);
|
|
620
1812
|
try {
|
|
621
|
-
const userId = "";
|
|
622
1813
|
const result = await checkInService.checkIn({
|
|
623
|
-
|
|
624
|
-
userId,
|
|
1814
|
+
branchId: params.branchId,
|
|
1815
|
+
userId: params.userId,
|
|
1816
|
+
entranceType: 0 /* ENTRY */,
|
|
625
1817
|
userLocation: location || void 0
|
|
626
1818
|
});
|
|
627
|
-
if (
|
|
628
|
-
|
|
1819
|
+
if (result.success) {
|
|
1820
|
+
return {
|
|
1821
|
+
success: true,
|
|
1822
|
+
data: result.entrance
|
|
1823
|
+
};
|
|
629
1824
|
}
|
|
630
|
-
return
|
|
1825
|
+
return {
|
|
1826
|
+
success: false,
|
|
1827
|
+
error: result.message || "Check-in failed"
|
|
1828
|
+
};
|
|
631
1829
|
} catch (err) {
|
|
632
|
-
|
|
633
|
-
|
|
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
|
+
};
|
|
634
1870
|
} finally {
|
|
635
1871
|
setIsLoading(false);
|
|
636
1872
|
}
|
|
637
1873
|
},
|
|
638
1874
|
[checkInService, location]
|
|
639
1875
|
);
|
|
640
|
-
(0, import_react6.useEffect)(() => {
|
|
641
|
-
if (options.autoFetch && location) {
|
|
642
|
-
fetchNearbyBranches();
|
|
643
|
-
}
|
|
644
|
-
}, [options.autoFetch, location, fetchNearbyBranches]);
|
|
645
1876
|
return {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
1877
|
+
getNearbyBranches,
|
|
1878
|
+
checkInEntry,
|
|
1879
|
+
checkInExit,
|
|
649
1880
|
isLoading,
|
|
650
1881
|
error
|
|
651
1882
|
};
|
|
652
1883
|
}
|
|
653
1884
|
|
|
654
|
-
// src/hooks/
|
|
1885
|
+
// src/hooks/usePassgageRemoteWork.ts
|
|
655
1886
|
var import_react7 = require("react");
|
|
656
|
-
|
|
657
|
-
function useRemoteWork() {
|
|
1887
|
+
function usePassgageRemoteWork() {
|
|
658
1888
|
const { remoteWorkService } = usePassgageAccess();
|
|
659
1889
|
const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
|
|
660
1890
|
const [error, setError] = (0, import_react7.useState)(null);
|
|
661
|
-
const
|
|
662
|
-
async (
|
|
1891
|
+
const logEntry = (0, import_react7.useCallback)(
|
|
1892
|
+
async (params) => {
|
|
663
1893
|
setIsLoading(true);
|
|
664
1894
|
setError(null);
|
|
665
1895
|
try {
|
|
666
|
-
const userId = "";
|
|
667
1896
|
const result = await remoteWorkService.logRemoteWork({
|
|
668
|
-
userId,
|
|
669
|
-
entranceType
|
|
670
|
-
timestamp:
|
|
671
|
-
description:
|
|
1897
|
+
userId: params.userId,
|
|
1898
|
+
entranceType: 0 /* ENTRY */,
|
|
1899
|
+
timestamp: params.timestamp,
|
|
1900
|
+
description: params.description
|
|
672
1901
|
});
|
|
673
|
-
if (
|
|
674
|
-
|
|
1902
|
+
if (result.success) {
|
|
1903
|
+
return {
|
|
1904
|
+
success: true,
|
|
1905
|
+
data: result.entrance
|
|
1906
|
+
};
|
|
675
1907
|
}
|
|
676
|
-
return
|
|
1908
|
+
return {
|
|
1909
|
+
success: false,
|
|
1910
|
+
error: result.message || "Failed to log entry"
|
|
1911
|
+
};
|
|
677
1912
|
} catch (err) {
|
|
678
1913
|
const error2 = err;
|
|
679
1914
|
setError(error2);
|
|
680
|
-
|
|
1915
|
+
return {
|
|
1916
|
+
success: false,
|
|
1917
|
+
error: error2.message || "Failed to log entry"
|
|
1918
|
+
};
|
|
681
1919
|
} finally {
|
|
682
1920
|
setIsLoading(false);
|
|
683
1921
|
}
|
|
684
1922
|
},
|
|
685
1923
|
[remoteWorkService]
|
|
686
1924
|
);
|
|
687
|
-
const logEntry = (0, import_react7.useCallback)(
|
|
688
|
-
async (options) => {
|
|
689
|
-
return logRemoteWork(import_sdk_core2.EntranceType.ENTRY, options);
|
|
690
|
-
},
|
|
691
|
-
[logRemoteWork]
|
|
692
|
-
);
|
|
693
1925
|
const logExit = (0, import_react7.useCallback)(
|
|
694
|
-
async (
|
|
695
|
-
|
|
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
|
+
}
|
|
696
1956
|
},
|
|
697
|
-
[
|
|
1957
|
+
[remoteWorkService]
|
|
698
1958
|
);
|
|
699
1959
|
return {
|
|
700
1960
|
logEntry,
|
|
701
1961
|
logExit,
|
|
702
|
-
logRemoteWork,
|
|
703
1962
|
isLoading,
|
|
704
1963
|
error
|
|
705
1964
|
};
|
|
706
1965
|
}
|
|
707
1966
|
|
|
708
|
-
// src/index.
|
|
709
|
-
var SDK_VERSION = "1.0.
|
|
1967
|
+
// src/index.ts
|
|
1968
|
+
var SDK_VERSION = "1.0.3";
|
|
710
1969
|
// Annotate the CommonJS export names for ESM import in node:
|
|
711
1970
|
0 && (module.exports = {
|
|
1971
|
+
ApiClient,
|
|
1972
|
+
AuthService,
|
|
1973
|
+
CheckInService,
|
|
1974
|
+
DeviceAccessService,
|
|
1975
|
+
DeviceDirection,
|
|
1976
|
+
DeviceUsage,
|
|
1977
|
+
Endpoints,
|
|
1978
|
+
EntranceType,
|
|
1979
|
+
LocationService,
|
|
1980
|
+
NFCAccessService,
|
|
712
1981
|
PassgageAccessProvider,
|
|
1982
|
+
QRAccessService,
|
|
1983
|
+
RemoteWorkService,
|
|
713
1984
|
SDK_VERSION,
|
|
714
|
-
|
|
1985
|
+
calculateDistance,
|
|
1986
|
+
checkOnLocation,
|
|
1987
|
+
checkRepetitiveRead,
|
|
1988
|
+
clearReadRecords,
|
|
1989
|
+
createApiClient,
|
|
1990
|
+
formatDate,
|
|
1991
|
+
formatDateTime,
|
|
1992
|
+
formatISO,
|
|
1993
|
+
formatTime,
|
|
1994
|
+
parseISO,
|
|
715
1995
|
useLocation,
|
|
716
|
-
useNFCScanner,
|
|
717
1996
|
usePassgageAccess,
|
|
718
1997
|
usePassgageAuth,
|
|
719
|
-
|
|
720
|
-
|
|
1998
|
+
usePassgageCheckIn,
|
|
1999
|
+
usePassgageNFCScanner,
|
|
2000
|
+
usePassgageQRScanner,
|
|
2001
|
+
usePassgageRemoteWork,
|
|
2002
|
+
validateCoordinates,
|
|
2003
|
+
validateDeviceId,
|
|
2004
|
+
validateNFCCode,
|
|
2005
|
+
validateQRCode
|
|
721
2006
|
});
|