@phygitallabs/tapquest-core 2.7.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +1035 -750
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +29 -35
  5. package/dist/index.d.ts +29 -35
  6. package/dist/index.js +1017 -717
  7. package/dist/index.js.map +1 -1
  8. package/package.json +10 -3
  9. package/src/modules/auth/constants/index.ts +6 -0
  10. package/src/modules/auth/helpers/index.ts +1 -4
  11. package/src/modules/auth/hooks/index.ts +2 -0
  12. package/src/modules/auth/hooks/useGoogleLogin.ts +169 -0
  13. package/src/modules/auth/hooks/useTokenRefresher.ts +39 -0
  14. package/src/modules/auth/index.ts +8 -2
  15. package/src/modules/auth/providers/AuthProvider.tsx +214 -186
  16. package/src/modules/auth/store/authStore.ts +577 -0
  17. package/src/modules/auth/types/auth.ts +29 -0
  18. package/src/modules/auth/types/user-data.ts +38 -0
  19. package/src/modules/auth/utils/user.ts +21 -0
  20. package/src/modules/data-tracking/hooks/index.ts +25 -1
  21. package/src/modules/generate-certificate/helpers/index.ts +3 -0
  22. package/src/modules/generate-certificate/hooks/index.ts +15 -6
  23. package/src/modules/generate-certificate/index.ts +3 -1
  24. package/src/modules/notification/providers/index.tsx +3 -3
  25. package/src/modules/reward/hooks/useRewardService.ts +6 -6
  26. package/src/modules/session-replay/README.md +334 -0
  27. package/src/modules/session-replay/hooks/useSessionReplay.ts +16 -0
  28. package/src/modules/session-replay/index.ts +10 -0
  29. package/src/modules/session-replay/providers/SessionReplayProvider.tsx +189 -0
  30. package/src/modules/session-replay/types/index.ts +147 -0
  31. package/src/modules/session-replay/utils/index.ts +12 -0
  32. package/src/providers/ServicesProvider.tsx +4 -76
  33. package/src/providers/TapquestCoreProvider.tsx +31 -36
  34. package/src/modules/auth/helpers/refreshToken.ts +0 -63
  35. package/src/modules/auth/store/authSlice.ts +0 -137
package/dist/index.js CHANGED
@@ -2,10 +2,6 @@ var __defProp = Object.defineProperty;
2
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __esm = (fn, res) => function __init() {
7
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
- };
9
5
  var __export = (target, all) => {
10
6
  for (var name in all)
11
7
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -19,325 +15,16 @@ var __copyProps = (to, from, except, desc) => {
19
15
  return to;
20
16
  };
21
17
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
22
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
23
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
24
-
25
- // src/modules/auth/constants/index.ts
26
- var userInfoKey, accessTokenKey, refreshTokenKey, httpMaxRetries, retryAttemptsRefreshToken, deviceUIDKey, chipAuthTokenKey;
27
- var init_constants = __esm({
28
- "src/modules/auth/constants/index.ts"() {
29
- "use strict";
30
- userInfoKey = "phygital-user-info";
31
- accessTokenKey = "accessToken";
32
- refreshTokenKey = "refreshToken";
33
- httpMaxRetries = 3;
34
- retryAttemptsRefreshToken = "retryAttemptsRefreshToken";
35
- deviceUIDKey = "Device-UID";
36
- chipAuthTokenKey = "chip-auth-token";
37
- }
38
- });
39
-
40
- // src/modules/auth/services/FirebaseAuthService.ts
41
- var firebaseApp, firebaseAuth, getFirebaseModules, FirebaseAuthService;
42
- var init_FirebaseAuthService = __esm({
43
- "src/modules/auth/services/FirebaseAuthService.ts"() {
44
- "use strict";
45
- init_constants();
46
- getFirebaseModules = async () => {
47
- if (typeof window === "undefined") {
48
- throw new Error("Firebase can only be used in client environment");
49
- }
50
- if (!firebaseApp || !firebaseAuth) {
51
- const [
52
- { initializeApp, getApps },
53
- {
54
- getAuth,
55
- signInWithEmailAndPassword,
56
- createUserWithEmailAndPassword,
57
- signInWithPopup,
58
- GoogleAuthProvider,
59
- signOut: signOut2,
60
- sendPasswordResetEmail,
61
- sendEmailVerification,
62
- updatePassword,
63
- onAuthStateChanged
64
- }
65
- ] = await Promise.all([
66
- import("firebase/app"),
67
- import("firebase/auth")
68
- ]);
69
- firebaseApp = { initializeApp, getApps };
70
- firebaseAuth = {
71
- getAuth,
72
- signInWithEmailAndPassword,
73
- createUserWithEmailAndPassword,
74
- signInWithPopup,
75
- GoogleAuthProvider,
76
- signOut: signOut2,
77
- sendPasswordResetEmail,
78
- sendEmailVerification,
79
- updatePassword,
80
- onAuthStateChanged
81
- };
82
- }
83
- return { firebaseApp, firebaseAuth };
84
- };
85
- FirebaseAuthService = class {
86
- constructor(config) {
87
- __publicField(this, "app");
88
- __publicField(this, "auth");
89
- __publicField(this, "googleProvider");
90
- __publicField(this, "config");
91
- __publicField(this, "initialized", false);
92
- this.config = config;
93
- }
94
- async ensureInitialized() {
95
- if (this.initialized) return;
96
- const { firebaseApp: firebaseApp2, firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
97
- if (!firebaseApp2.getApps().length) {
98
- this.app = firebaseApp2.initializeApp(this.config);
99
- } else {
100
- this.app = firebaseApp2.getApps()[0];
101
- }
102
- this.auth = firebaseAuth2.getAuth(this.app);
103
- this.googleProvider = new firebaseAuth2.GoogleAuthProvider();
104
- this.initialized = true;
105
- }
106
- transformUserData(user) {
107
- return {
108
- id: user.uid,
109
- uid: user.uid,
110
- userName: user.displayName || "",
111
- displayName: user.displayName || "",
112
- email: user.email || "",
113
- refreshToken: user.refreshToken,
114
- accessToken: user.accessToken || "",
115
- exp: user.stsTokenManager?.expirationTime || 0,
116
- emailVerified: user.emailVerified,
117
- avatar: user.photoURL || "/images/default-avatar.jpg",
118
- signInProvider: this.getSignInProvider(user),
119
- role: void 0,
120
- scanStatus: false
121
- };
122
- }
123
- getSignInProvider(user) {
124
- const providers = user.providerData.map((p) => p.providerId);
125
- if (providers.includes("google.com")) return "google.com";
126
- return "password";
127
- }
128
- translateErrorCode(errorCode) {
129
- switch (errorCode) {
130
- case "auth/invalid-email":
131
- return "Email kh\xF4ng h\u1EE3p l\u1EC7";
132
- case "auth/user-disabled":
133
- return "T\xE0i kho\u1EA3n \u0111\xE3 b\u1ECB kh\xF3a";
134
- case "auth/wrong-password":
135
- return "T\xE0i kho\u1EA3n/m\u1EADt kh\u1EA9u kh\xF4ng \u0111\xFAng";
136
- case "auth/user-not-found":
137
- return "T\xE0i kho\u1EA3n/m\u1EADt kh\u1EA9u kh\xF4ng \u0111\xFAng";
138
- case "auth/weak-password":
139
- return "Weak password! Please use stronger password.";
140
- case "auth/email-already-in-use":
141
- return "Email \u0111\xE3 \u0111\u01B0\u1EE3c s\u1EED d\u1EE5ng";
142
- case "auth/account-exists-with-different-credential":
143
- return "T\xE0i kho\u1EA3n email \u0111\xE3 \u0111\u01B0\u1EE3c s\u1EED d\u1EE5ng b\u1EDFi m\u1ED9t ph\u01B0\u01A1ng th\u1EE9c \u0111\u0103ng nh\u1EADp kh\xE1c";
144
- case "auth/email-not-verified":
145
- return "Email ch\u01B0a \u0111\u01B0\u1EE3c x\xE1c th\u1EF1c";
146
- default:
147
- return "\u0110\xE3 c\xF3 l\u1ED7i x\u1EA3y ra";
148
- }
149
- }
150
- async signInWithEmailAndPassword(email, password) {
151
- try {
152
- await this.ensureInitialized();
153
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
154
- const signInResponse = await firebaseAuth2.signInWithEmailAndPassword(this.auth, email, password);
155
- const { user } = signInResponse;
156
- const data = this.transformUserData(user);
157
- const { emailVerified } = data;
158
- if (!emailVerified) {
159
- await this.signOut();
160
- localStorage.removeItem("phygital-user-info");
161
- localStorage.removeItem(accessTokenKey);
162
- localStorage.removeItem(refreshTokenKey);
163
- throw new Error("Email is not verified");
164
- }
165
- return {
166
- errorCode: "",
167
- data
168
- };
169
- } catch (err) {
170
- const errorCode = this.translateErrorCode(err.code);
171
- return {
172
- errorCode,
173
- data: null
174
- };
175
- }
176
- }
177
- async signInWithGoogle() {
178
- try {
179
- await this.ensureInitialized();
180
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
181
- const signInResponse = await firebaseAuth2.signInWithPopup(this.auth, this.googleProvider);
182
- const { user } = signInResponse;
183
- const data = this.transformUserData(user);
184
- const { emailVerified } = data;
185
- if (!emailVerified) {
186
- await this.signOut();
187
- throw new Error("Email is not verified");
188
- }
189
- return {
190
- errorCode: "",
191
- data
192
- };
193
- } catch (err) {
194
- const errorCode = this.translateErrorCode(err.code);
195
- return {
196
- errorCode,
197
- data: null
198
- };
199
- }
200
- }
201
- async signUp(email, password) {
202
- try {
203
- await this.ensureInitialized();
204
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
205
- const signUpResponse = await firebaseAuth2.createUserWithEmailAndPassword(this.auth, email, password);
206
- const { user } = signUpResponse;
207
- const data = this.transformUserData(user);
208
- return {
209
- errorCode: "",
210
- data
211
- };
212
- } catch (err) {
213
- const errorCode = this.translateErrorCode(err.code);
214
- return {
215
- errorCode,
216
- data: null
217
- };
218
- }
219
- }
220
- async signOut() {
221
- try {
222
- await this.ensureInitialized();
223
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
224
- await firebaseAuth2.signOut(this.auth);
225
- } catch (err) {
226
- console.log("Firebase signOut error:", err);
227
- }
228
- }
229
- async sendPasswordResetEmail(email) {
230
- await this.ensureInitialized();
231
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
232
- const actionCodeSettings = {
233
- url: window.location.origin,
234
- handleCodeInApp: true
235
- };
236
- await firebaseAuth2.sendPasswordResetEmail(this.auth, email, actionCodeSettings);
237
- }
238
- async sendEmailVerification() {
239
- await this.ensureInitialized();
240
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
241
- if (!this.auth.currentUser) {
242
- throw new Error("No current user");
243
- }
244
- const actionCodeSettings = {
245
- url: window.location.origin,
246
- handleCodeInApp: true
247
- };
248
- await firebaseAuth2.sendEmailVerification(this.auth.currentUser, actionCodeSettings);
249
- }
250
- async changePassword(newPassword) {
251
- await this.ensureInitialized();
252
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
253
- const user = this.auth.currentUser;
254
- if (!user) {
255
- throw new Error("No current user");
256
- }
257
- return firebaseAuth2.updatePassword(user, newPassword);
258
- }
259
- onAuthStateChanged(callback) {
260
- if (typeof window === "undefined") {
261
- return () => {
262
- };
263
- }
264
- let unsubscriber = null;
265
- this.ensureInitialized().then(async () => {
266
- const { firebaseAuth: firebaseAuth2 } = await getFirebaseModules();
267
- unsubscriber = firebaseAuth2.onAuthStateChanged(this.auth, (user) => {
268
- if (user && user.emailVerified) {
269
- const userData = this.transformUserData(user);
270
- callback(userData);
271
- } else {
272
- callback(null);
273
- }
274
- });
275
- });
276
- return () => {
277
- if (unsubscriber) {
278
- unsubscriber();
279
- }
280
- };
281
- }
282
- getCurrentUser() {
283
- if (typeof window === "undefined" || !this.initialized) {
284
- return null;
285
- }
286
- const user = this.auth.currentUser;
287
- if (user && user.emailVerified) {
288
- return this.transformUserData(user);
289
- }
290
- return null;
291
- }
292
- };
293
- }
294
- });
295
-
296
- // src/modules/auth/services/authServiceFactory.ts
297
- var authServiceInstance, createAuthService, getAuthService, resetAuthService;
298
- var init_authServiceFactory = __esm({
299
- "src/modules/auth/services/authServiceFactory.ts"() {
300
- "use strict";
301
- init_FirebaseAuthService();
302
- authServiceInstance = null;
303
- createAuthService = (config) => {
304
- if (!authServiceInstance) {
305
- authServiceInstance = new FirebaseAuthService(config.firebaseConfig);
306
- }
307
- return authServiceInstance;
308
- };
309
- getAuthService = () => {
310
- return authServiceInstance;
311
- };
312
- resetAuthService = () => {
313
- authServiceInstance = null;
314
- };
315
- }
316
- });
317
-
318
- // src/modules/auth/services/index.ts
319
- var services_exports = {};
320
- __export(services_exports, {
321
- FirebaseAuthService: () => FirebaseAuthService,
322
- createAuthService: () => createAuthService,
323
- getAuthService: () => getAuthService,
324
- resetAuthService: () => resetAuthService
325
- });
326
- var init_services = __esm({
327
- "src/modules/auth/services/index.ts"() {
328
- "use strict";
329
- init_FirebaseAuthService();
330
- init_authServiceFactory();
331
- }
332
- });
333
18
 
334
19
  // src/index.ts
335
20
  var index_exports = {};
336
21
  __export(index_exports, {
22
+ ALLOWED_ORIGINS: () => ALLOWED_ORIGINS,
337
23
  AchievementRuleActionType: () => AchievementRuleActionType,
338
24
  AchievementServiceProvider: () => AchievementServiceProvider,
339
25
  AchievementType: () => AchievementType,
340
26
  AuthProvider: () => AuthProvider,
27
+ CALLBACK_URL: () => CALLBACK_URL,
341
28
  CampaignState: () => CampaignState,
342
29
  CmentityRewardType: () => CmentityRewardType,
343
30
  NotificationProvider: () => NotificationProvider,
@@ -350,7 +37,6 @@ __export(index_exports, {
350
37
  chipAuthTokenKey: () => chipAuthTokenKey,
351
38
  cn: () => cn,
352
39
  convertSnakeToCamel: () => convertSnakeToCamel,
353
- createRefreshTokenFunction: () => createRefreshTokenFunction,
354
40
  deviceUIDKey: () => deviceUIDKey,
355
41
  fileToBase64: () => fileToBase64,
356
42
  filterLocationsByProperty: () => filterLocationsByProperty,
@@ -391,18 +77,22 @@ __export(index_exports, {
391
77
  useChipScanStory: () => useChipScanStory,
392
78
  useClaimUserReward: () => useClaimUserReward,
393
79
  useClearUserRewardCache: () => useClearUserRewardCache,
80
+ useCreateCertificate: () => useCreateCertificate,
81
+ useCreateCertificateAnonymous: () => useCreateCertificateAnonymous,
82
+ useCreateCertificateWithMask: () => useCreateCertificateWithMask,
394
83
  useCreateMemory: () => useCreateMemory,
395
84
  useCreateModelGroupReward: () => useCreateModelGroupReward,
396
- useCreateRewardModel: () => useApiCreateRewardModel,
85
+ useCreateRewardModel: () => useCreateRewardModel,
397
86
  useDataTracking: () => useDataTracking,
398
- useDeleteRewardModel: () => useApiDeleteRewardModel,
87
+ useDeleteRewardModel: () => useDeleteRewardModel,
399
88
  useGenerateFansipanCertificate: () => useGenerateFansipanCertificate,
400
89
  useGenerateTemplateCertificate: () => useGenerateTemplateCertificate,
401
90
  useGenerateThaocamvienCertificate: () => useGenerateThaocamvienCertificate,
402
- useGetRewardModel: () => useApiGetRewardModel,
91
+ useGetRewardModel: () => useGetRewardModel,
403
92
  useGetUserRewards: () => useGetUserRewards,
93
+ useGoogleLogin: () => useGoogleLogin,
404
94
  useInfiniteMemories: () => useInfiniteMemories,
405
- useListRewardModels: () => useApiListRewardModels,
95
+ useListRewardModels: () => useListRewardModels,
406
96
  useLocationDetail: () => useOneLocation,
407
97
  useLocationProgress: () => useUserCampaignsCompletedLocation,
408
98
  useLocationsList: () => useManyLocations,
@@ -417,17 +107,18 @@ __export(index_exports, {
417
107
  useOneAchievement: () => useOneAchievement,
418
108
  useOneMemory: () => useOneMemory,
419
109
  useOneUserCampaign: () => useOneUserCampaign,
420
- usePGLCoreService: () => usePGLCoreService,
110
+ usePGLCoreService: () => usePGLCoreService2,
421
111
  useScanChip: () => useScanChip,
422
112
  useSendEmail: () => useSendEmail,
423
113
  useSyncCheckin: () => useSyncCheckin,
424
114
  useUpdateMyProfile: () => useUpdateMyProfile,
425
- useUpdateRewardModel: () => useApiUpdateRewardModel,
115
+ useUpdateRewardModel: () => useUpdateRewardModel,
426
116
  useUploadMedia: () => useUploadMedia,
427
117
  useUserAchievementAction: () => useUserAchievementAction,
428
118
  useUserCampaignAction: () => useUserCampaignAction,
429
119
  useV1ListRewards: () => useV1ListRewards,
430
- userInfoKey: () => userInfoKey
120
+ userInfoKey: () => userInfoKey,
121
+ wrapTextWithFont: () => wrapTextWithFont
431
122
  });
432
123
 
433
124
  // src/modules/achievement/hooks/index.ts
@@ -566,15 +257,15 @@ import {
566
257
  useManyUserRewards,
567
258
  useGetUserRewards,
568
259
  useClaimUserReward,
569
- useApiListRewardModels,
570
- useApiGetRewardModel,
571
- useApiCreateRewardModel,
572
- useApiUpdateRewardModel,
573
- useApiDeleteRewardModel,
260
+ useListRewardModels,
261
+ useGetRewardModel,
262
+ useCreateRewardModel,
263
+ useUpdateRewardModel,
264
+ useDeleteRewardModel,
574
265
  useCreateModelGroupReward,
575
266
  useClearUserRewardCache,
576
267
  useV1ListRewards
577
- } from "@phygitallabs/reward/src/hooks";
268
+ } from "@phygitallabs/reward";
578
269
 
579
270
  // src/modules/reward/types/enums.ts
580
271
  import {
@@ -643,8 +334,8 @@ var NotificationProvider = ({
643
334
  return /* @__PURE__ */ jsx(
644
335
  NotificationProviderApi,
645
336
  {
646
- userUid: user.id,
647
- accessToken: user.accessToken,
337
+ userUid: user?.id,
338
+ accessToken: user?.accessToken ?? null,
648
339
  webSocketUrl,
649
340
  autoConnect,
650
341
  onWebSocketOpen,
@@ -662,69 +353,774 @@ __reExport(index_exports, notification_exports);
662
353
  import { useOneMemory, useManyMemory, useInfiniteMemories, useCreateMemory, useUploadMedia, resetMemoriesQuery, memoriesKey } from "@phygitallabs/api-core";
663
354
 
664
355
  // src/modules/auth/providers/AuthProvider.tsx
665
- import { createContext, useEffect, useContext } from "react";
356
+ import {
357
+ AuthenticationProvider,
358
+ useAuthenticationHeaders,
359
+ tokenStorage as tokenStorage3
360
+ } from "@phygitallabs/authentication";
361
+ import { useEffect } from "react";
666
362
 
667
- // src/store/hooks.ts
668
- import { useDispatch, useSelector } from "react-redux";
669
- var useAppDispatch = () => useDispatch();
670
- var useAppSelector = useSelector;
363
+ // src/modules/auth/store/authStore.ts
364
+ import { create } from "zustand";
365
+ import { immer } from "zustand/middleware/immer";
366
+ import {
367
+ createJSONStorage,
368
+ devtools,
369
+ persist,
370
+ subscribeWithSelector
371
+ } from "zustand/middleware";
372
+ import {
373
+ authService,
374
+ verifyCodeService,
375
+ tokenStorage
376
+ } from "@phygitallabs/authentication";
671
377
 
672
- // src/modules/auth/store/authSlice.ts
673
- import { createSlice } from "@reduxjs/toolkit";
378
+ // src/modules/auth/constants/index.ts
379
+ var userInfoKey = "phygital-user-info";
380
+ var accessTokenKey = "accessToken";
381
+ var refreshTokenKey = "refreshToken";
382
+ var httpMaxRetries = 3;
383
+ var retryAttemptsRefreshToken = "retryAttemptsRefreshToken";
384
+ var deviceUIDKey = "Device-UID";
385
+ var chipAuthTokenKey = "chip-auth-token";
386
+ var CALLBACK_URL = "https://s3-sgn10.fptcloud.com/nomion-assets/platform/callback.html";
387
+ var ALLOWED_ORIGINS = [
388
+ "https://s3-sgn10.fptcloud.com",
389
+ "https://accounts.google.com/"
390
+ ];
674
391
 
675
- // src/modules/auth/helpers/index.ts
676
- init_constants();
677
- import { v4 as uuidv4 } from "uuid";
392
+ // src/modules/auth/store/authStore.ts
393
+ var initialState = {
394
+ user: null,
395
+ isSignedIn: false,
396
+ isInitialized: false,
397
+ isLoading: false,
398
+ error: null,
399
+ cleanupFunctions: {},
400
+ eventCallbacks: {}
401
+ };
402
+ var useAuthStore = create()(
403
+ devtools(
404
+ persist(
405
+ subscribeWithSelector(
406
+ immer((set, get) => ({
407
+ ...initialState,
408
+ actions: {
409
+ setIsLoading: (isLoading) => set((state) => {
410
+ state.isLoading = isLoading;
411
+ }),
412
+ setCleanupFunctions: (newCleanupFunctions) => set((state) => {
413
+ state.cleanupFunctions = {
414
+ ...state.cleanupFunctions,
415
+ ...newCleanupFunctions
416
+ };
417
+ }),
418
+ // Event management
419
+ addEventCallbacks: (callbacks) => {
420
+ set((state) => {
421
+ state.eventCallbacks = {
422
+ ...state.eventCallbacks,
423
+ ...callbacks
424
+ };
425
+ });
426
+ return () => {
427
+ set((state) => {
428
+ state.eventCallbacks = {
429
+ ...state.eventCallbacks,
430
+ ...callbacks
431
+ };
432
+ });
433
+ };
434
+ },
435
+ // Sign in with email and password
436
+ signInWithEmail: async (email, password) => {
437
+ const { eventCallbacks } = get();
438
+ set((state) => {
439
+ state.isLoading = true;
440
+ state.error = null;
441
+ });
442
+ try {
443
+ const response = await authService.signIn({
444
+ email,
445
+ password
446
+ });
447
+ if (response?.data?.idToken && response?.data?.refreshToken) {
448
+ tokenStorage.setTokens({
449
+ idToken: response.data.idToken,
450
+ refreshToken: response.data.refreshToken
451
+ });
452
+ set((state) => {
453
+ state.isSignedIn = true;
454
+ });
455
+ eventCallbacks.onLoginSuccess?.(response.data.idToken);
456
+ }
457
+ return response;
458
+ } catch (error) {
459
+ if (error?.response?.data?.code === 7) {
460
+ return {
461
+ data: void 0,
462
+ message: "Email verification required",
463
+ code: 7
464
+ };
465
+ }
466
+ const errorMessage = error instanceof Error ? error.message : "Login failed";
467
+ set((state) => {
468
+ state.error = errorMessage;
469
+ });
470
+ eventCallbacks.onLoginError?.(new Error(errorMessage));
471
+ throw error;
472
+ } finally {
473
+ set((state) => {
474
+ state.isLoading = false;
475
+ });
476
+ }
477
+ },
478
+ // Sign in with Google
479
+ signInWithGoogle: async () => {
480
+ const { eventCallbacks } = get();
481
+ try {
482
+ const currentDomain = CALLBACK_URL;
483
+ const userData = await authService.getOAuthSignInUrl(currentDomain);
484
+ return userData;
485
+ } catch (error) {
486
+ const errorMessage = error instanceof Error ? error.message : "Google sign in failed";
487
+ set((state) => {
488
+ state.error = errorMessage;
489
+ });
490
+ eventCallbacks.onLoginError?.(new Error(errorMessage));
491
+ throw error;
492
+ }
493
+ },
494
+ // Sign up with email and password
495
+ signUpWithEmail: async (email, password) => {
496
+ const { eventCallbacks } = get();
497
+ set((state) => {
498
+ state.isLoading = true;
499
+ state.error = null;
500
+ });
501
+ try {
502
+ const response = await authService.signUp({
503
+ email,
504
+ password
505
+ });
506
+ if (response.data) {
507
+ eventCallbacks.onSignupSuccess?.();
508
+ }
509
+ return response;
510
+ } catch (error) {
511
+ const errorMessage = error instanceof Error ? error.message : "Signup failed";
512
+ set((state) => {
513
+ state.error = errorMessage;
514
+ });
515
+ eventCallbacks.onSignupError?.(new Error(errorMessage));
516
+ throw error;
517
+ } finally {
518
+ set((state) => {
519
+ state.isLoading = false;
520
+ state.user = null;
521
+ state.isSignedIn = false;
522
+ });
523
+ }
524
+ },
525
+ // Sign out
526
+ signOut: async () => {
527
+ const { eventCallbacks, cleanupFunctions } = get();
528
+ set((state) => {
529
+ state.isLoading = true;
530
+ state.error = null;
531
+ });
532
+ try {
533
+ set((state) => {
534
+ state.user = null;
535
+ state.isSignedIn = false;
536
+ state.error = null;
537
+ });
538
+ const isTokenExpired = tokenStorage.isTokenExpired();
539
+ if (isTokenExpired) {
540
+ tokenStorage.clearTokens();
541
+ localStorage.clear();
542
+ return;
543
+ }
544
+ await authService.logout();
545
+ localStorage.clear();
546
+ tokenStorage.clearTokens();
547
+ try {
548
+ cleanupFunctions.clearQueryCache?.();
549
+ cleanupFunctions.clearOrganization?.();
550
+ cleanupFunctions.clearCustomData?.();
551
+ cleanupFunctions.clearHeaders?.();
552
+ } catch (cleanupError) {
553
+ console.warn("Error during logout cleanup:", cleanupError);
554
+ }
555
+ eventCallbacks.onLogoutSuccess?.();
556
+ } catch (error) {
557
+ console.log(error);
558
+ const errorMessage = error instanceof Error ? error.message : "Logout failed";
559
+ set((state) => {
560
+ state.error = errorMessage;
561
+ });
562
+ eventCallbacks.onLogoutError?.(new Error(errorMessage));
563
+ throw error;
564
+ } finally {
565
+ set((state) => {
566
+ state.isLoading = false;
567
+ });
568
+ }
569
+ },
570
+ // Send password reset email
571
+ sendPasswordResetEmail: async (email) => {
572
+ set((state) => {
573
+ state.isLoading = true;
574
+ state.error = null;
575
+ });
576
+ try {
577
+ await verifyCodeService.forgotPassword({
578
+ email
579
+ });
580
+ } catch (error) {
581
+ const errorMessage = error instanceof Error ? error.message : "Failed to send reset email";
582
+ set((state) => {
583
+ state.error = errorMessage;
584
+ });
585
+ throw error;
586
+ } finally {
587
+ set((state) => {
588
+ state.isLoading = false;
589
+ });
590
+ }
591
+ },
592
+ resetPassword: async (data) => {
593
+ set((state) => {
594
+ state.isLoading = true;
595
+ state.error = null;
596
+ });
597
+ try {
598
+ const resetPasswordResponse = await verifyCodeService.resetPassword(data);
599
+ return resetPasswordResponse;
600
+ } catch (error) {
601
+ const errorMessage = error instanceof Error ? error.message : "Failed to reset password";
602
+ set((state) => {
603
+ state.error = errorMessage;
604
+ });
605
+ throw error;
606
+ } finally {
607
+ set((state) => {
608
+ state.isLoading = false;
609
+ });
610
+ }
611
+ },
612
+ changePassword: async (data) => {
613
+ set((state) => {
614
+ state.isLoading = true;
615
+ state.error = null;
616
+ });
617
+ try {
618
+ const changePasswordResponse = await verifyCodeService.changePassword(data);
619
+ return changePasswordResponse;
620
+ } catch (error) {
621
+ throw error;
622
+ } finally {
623
+ set((state) => {
624
+ state.isLoading = false;
625
+ });
626
+ }
627
+ },
628
+ verifyEmailCode: async (data) => {
629
+ set((state) => {
630
+ state.isLoading = true;
631
+ state.error = null;
632
+ });
633
+ try {
634
+ const verifyEmailResponse = await verifyCodeService.verifyEmail(data);
635
+ return verifyEmailResponse;
636
+ } catch (error) {
637
+ const errorMessage = error instanceof Error ? error.message : "Failed to send reset email";
638
+ set((state) => {
639
+ state.error = errorMessage;
640
+ });
641
+ throw error;
642
+ } finally {
643
+ set((state) => {
644
+ state.isLoading = false;
645
+ });
646
+ }
647
+ },
648
+ sendVerifyCode: async (data) => {
649
+ set((state) => {
650
+ state.isLoading = true;
651
+ state.error = null;
652
+ });
653
+ try {
654
+ const sendVerifyCodeResponse = await verifyCodeService.sendVerifyCode(data);
655
+ return sendVerifyCodeResponse;
656
+ } catch (error) {
657
+ const errorMessage = error instanceof Error ? error.message : "Failed to send verify code";
658
+ set((state) => {
659
+ state.error = errorMessage;
660
+ });
661
+ throw error;
662
+ } finally {
663
+ set((state) => {
664
+ state.isLoading = false;
665
+ });
666
+ }
667
+ },
668
+ refreshToken: async (refreshToken) => {
669
+ const refreshTokenResponse = await authService.refreshToken({
670
+ refreshToken: refreshToken ?? tokenStorage.getRefreshToken() ?? ""
671
+ });
672
+ return refreshTokenResponse;
673
+ },
674
+ // Clear error
675
+ clearError: () => set((state) => {
676
+ state.error = null;
677
+ }),
678
+ setUser: (user) => set((state) => {
679
+ state.user = user;
680
+ }),
681
+ setIsSignedIn: (isSignedIn) => set((state) => {
682
+ state.isSignedIn = isSignedIn;
683
+ }),
684
+ setIsInitialized: (isInitialized) => set((state) => {
685
+ state.isInitialized = isInitialized;
686
+ }),
687
+ patchUser: (user) => set((state) => {
688
+ if (state.user) {
689
+ state.user = { ...state.user, ...user };
690
+ } else {
691
+ state.user = user;
692
+ }
693
+ }),
694
+ // Initialize the store - check if user is already authenticated from tokenStorage
695
+ initialize: () => {
696
+ set((state) => {
697
+ const token = tokenStorage.getAuthToken();
698
+ state.isSignedIn = !!token;
699
+ state.isInitialized = true;
700
+ });
701
+ },
702
+ // Sync auth state from tokenStorage (called when axios interceptor updates tokens)
703
+ syncAuthState: () => {
704
+ set((state) => {
705
+ const token = tokenStorage.getAuthToken();
706
+ const wasSignedIn = state.isSignedIn;
707
+ state.isSignedIn = !!token;
708
+ if (wasSignedIn !== state.isSignedIn) {
709
+ if (state.isSignedIn) {
710
+ state.eventCallbacks?.onAuthStateChange?.(state.user, true);
711
+ } else {
712
+ state.eventCallbacks?.onAuthStateChange?.(null, false);
713
+ }
714
+ }
715
+ });
716
+ }
717
+ }
718
+ }))
719
+ ),
720
+ {
721
+ version: 1,
722
+ name: "auth-store",
723
+ storage: createJSONStorage(() => localStorage),
724
+ partialize: (state) => ({
725
+ isSignedIn: state.isSignedIn,
726
+ user: state.user
727
+ })
728
+ }
729
+ )
730
+ )
731
+ );
732
+ var useAuth = () => {
733
+ const user = useAuthStore((state) => state.user);
734
+ const isSignedIn = useAuthStore((state) => state.isSignedIn);
735
+ const isInitialized = useAuthStore((state) => state.isInitialized);
736
+ const isLoading = useAuthStore((state) => state.isLoading);
737
+ const error = useAuthStore((state) => state.error);
738
+ const actions = useAuthStore((state) => state.actions);
739
+ return {
740
+ user,
741
+ isSignedIn,
742
+ isInitialized,
743
+ isLoading,
744
+ error,
745
+ ...actions
746
+ };
747
+ };
678
748
 
679
- // src/modules/auth/helpers/refreshToken.ts
680
- import mem from "mem";
681
- var REFRESH_TOKEN_CONFIG = {
682
- maxAge: 1e4
683
- // 10 seconds cache
749
+ // src/modules/auth/utils/user.ts
750
+ import jwtDecode from "jwt-decode";
751
+ var transformProtoUserData = (user, accessToken) => {
752
+ const userData = { ...user };
753
+ let tokenDecoded = {};
754
+ try {
755
+ tokenDecoded = jwtDecode(accessToken);
756
+ } catch (error) {
757
+ console.warn("Failed to decode token in transformUserData:", error);
758
+ }
759
+ userData.exp = tokenDecoded.exp || 0;
760
+ userData.accessToken = accessToken || "";
761
+ userData.roles = tokenDecoded?.roles || ["USER" /* USER */];
762
+ userData.account_type = tokenDecoded?.account_type || 0 /* C */;
763
+ userData.picture = user.picture || "";
764
+ return userData;
684
765
  };
685
- var createRefreshTokenFunction = (config) => {
686
- const refreshTokenFn = async () => {
766
+
767
+ // src/modules/auth/providers/AuthProvider.tsx
768
+ import { userService } from "@phygitallabs/api-core";
769
+ import { usePGLCoreService } from "@phygitallabs/api-core";
770
+ import { useAchievementService } from "@phygitallabs/achievement";
771
+ import { useRewardService } from "@phygitallabs/reward";
772
+ import { useGenerateCertificateService } from "@phygitallabs/generate-certificate";
773
+
774
+ // src/modules/auth/hooks/useTokenRefresher.ts
775
+ import { useQuery } from "@tanstack/react-query";
776
+ import { tokenStorage as tokenStorage2 } from "@phygitallabs/authentication";
777
+ function useTokenRefresher() {
778
+ const { refreshToken, signOut } = useAuth();
779
+ const handleRefreshToken = async () => {
687
780
  try {
688
- const session = getUserInfo();
689
- const refreshToken = getRefreshToken();
690
- if (!refreshToken) {
691
- removeUserInfo();
781
+ const isTokenExpired = tokenStorage2.isTokenExpired();
782
+ if (!isTokenExpired) {
692
783
  return;
693
784
  }
694
- const params = new URLSearchParams();
695
- params.append("grant_type", "refresh_token");
696
- params.append("refresh_token", refreshToken);
697
- const fetchData = {
698
- method: "POST",
699
- headers: new Headers({
700
- "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
701
- }),
702
- body: params
703
- };
704
- const response = await fetch(
705
- `https://securetoken.googleapis.com/v1/token?key=${config.firebaseApiKey}`,
706
- fetchData
785
+ const newToken = await refreshToken();
786
+ if (newToken.data?.idToken && newToken.data?.refreshToken) {
787
+ tokenStorage2.setTokens({
788
+ idToken: newToken.data?.idToken,
789
+ refreshToken: newToken.data?.refreshToken
790
+ });
791
+ }
792
+ } catch (error) {
793
+ console.error("Failed to refresh token:", error);
794
+ signOut();
795
+ }
796
+ };
797
+ useQuery({
798
+ queryKey: ["refresh-token"],
799
+ queryFn: () => handleRefreshToken(),
800
+ refetchInterval: 30 * 60 * 1e3,
801
+ // every 30 minutes
802
+ refetchIntervalInBackground: false,
803
+ // even when tab is hidden
804
+ refetchOnWindowFocus: true,
805
+ // also refresh when user returns to tab
806
+ retry: false,
807
+ // don't retry repeatedly if refresh fails
808
+ enabled: !!tokenStorage2.getAuthToken()
809
+ // only run if logged in
810
+ });
811
+ }
812
+
813
+ // src/modules/auth/providers/AuthProvider.tsx
814
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
815
+ var AuthStateManager = () => {
816
+ const { updateHeaders } = useAuthenticationHeaders();
817
+ const { updateHeaders: updateHeadersPGL, coreApi } = usePGLCoreService();
818
+ const { updateHeaders: updateHeadersAchievement } = useAchievementService();
819
+ const { updateHeaders: updateHeadersReward } = useRewardService();
820
+ const { updateHeaders: updateHeadersGenerateCertificate } = useGenerateCertificateService();
821
+ useEffect(() => {
822
+ useAuthStore.getState().actions.initialize();
823
+ const token = tokenStorage3.getAuthToken();
824
+ if (token) {
825
+ updateHeaders({
826
+ Authorization: `Bearer ${token}`
827
+ });
828
+ updateHeadersPGL({
829
+ Authorization: `Bearer ${token}`
830
+ });
831
+ updateHeadersAchievement({
832
+ Authorization: `Bearer ${token}`
833
+ });
834
+ updateHeadersReward({
835
+ Authorization: `Bearer ${token}`
836
+ });
837
+ updateHeadersGenerateCertificate({
838
+ Authorization: `Bearer ${token}`
839
+ });
840
+ const { user } = useAuthStore.getState();
841
+ if (user && user.accessToken !== token) {
842
+ useAuthStore.getState().actions.setUser({
843
+ ...user,
844
+ accessToken: token
845
+ });
846
+ }
847
+ }
848
+ let previousIsSignedIn = useAuthStore.getState().isSignedIn;
849
+ const unsub = useAuthStore.subscribe(
850
+ (state) => [state.isSignedIn, state.user],
851
+ async ([isSignedIn]) => {
852
+ if (isSignedIn === previousIsSignedIn) {
853
+ return;
854
+ }
855
+ previousIsSignedIn = isSignedIn;
856
+ if (isSignedIn) {
857
+ const token2 = tokenStorage3.getAuthToken();
858
+ if (token2) {
859
+ updateHeaders({
860
+ Authorization: `Bearer ${token2}`
861
+ });
862
+ updateHeadersPGL({
863
+ Authorization: `Bearer ${token2}`
864
+ });
865
+ updateHeadersAchievement({
866
+ Authorization: `Bearer ${token2}`
867
+ });
868
+ updateHeadersReward({
869
+ Authorization: `Bearer ${token2}`
870
+ });
871
+ updateHeadersGenerateCertificate({
872
+ Authorization: `Bearer ${token2}`
873
+ });
874
+ try {
875
+ const userApi = userService(coreApi);
876
+ const userProfile = await userApi.getMyProfile();
877
+ const transformedUserData = transformProtoUserData(
878
+ userProfile,
879
+ token2
880
+ );
881
+ useAuthStore.getState().actions.setUser(transformedUserData);
882
+ } catch (error) {
883
+ useAuthStore.getState().actions.signOut();
884
+ }
885
+ }
886
+ const { eventCallbacks, user } = useAuthStore.getState();
887
+ eventCallbacks?.onAuthStateChange?.(user, true);
888
+ } else {
889
+ updateHeaders({});
890
+ updateHeadersPGL({});
891
+ updateHeadersAchievement({
892
+ Authorization: ``
893
+ });
894
+ updateHeadersReward({
895
+ Authorization: ``
896
+ });
897
+ updateHeadersGenerateCertificate({
898
+ Authorization: ``
899
+ });
900
+ const { eventCallbacks } = useAuthStore.getState();
901
+ eventCallbacks?.onAuthStateChange?.(null, false);
902
+ }
903
+ }
904
+ );
905
+ const unsubTokenChange = tokenStorage3.addTokenChangeListener(async () => {
906
+ const { isSignedIn, user } = useAuthStore.getState();
907
+ if (isSignedIn) {
908
+ const token2 = tokenStorage3.getAuthToken();
909
+ if (token2) {
910
+ updateHeaders({
911
+ Authorization: `Bearer ${token2}`
912
+ });
913
+ updateHeadersPGL({
914
+ Authorization: `Bearer ${token2}`
915
+ });
916
+ updateHeadersAchievement({
917
+ Authorization: `Bearer ${token2}`
918
+ });
919
+ updateHeadersReward({
920
+ Authorization: `Bearer ${token2}`
921
+ });
922
+ updateHeadersGenerateCertificate({
923
+ Authorization: `Bearer ${token2}`
924
+ });
925
+ if (user && user.accessToken !== token2) {
926
+ useAuthStore.getState().actions.setUser({
927
+ ...user,
928
+ accessToken: token2
929
+ });
930
+ }
931
+ } else {
932
+ useAuthStore.getState().actions.signOut();
933
+ updateHeaders({});
934
+ updateHeadersPGL({});
935
+ updateHeadersAchievement({
936
+ Authorization: ``
937
+ });
938
+ updateHeadersReward({
939
+ Authorization: ``
940
+ });
941
+ updateHeadersGenerateCertificate({
942
+ Authorization: ``
943
+ });
944
+ }
945
+ }
946
+ });
947
+ return () => {
948
+ unsub();
949
+ unsubTokenChange();
950
+ };
951
+ }, [
952
+ updateHeaders,
953
+ updateHeadersPGL,
954
+ updateHeadersAchievement,
955
+ updateHeadersReward,
956
+ updateHeadersGenerateCertificate,
957
+ coreApi
958
+ ]);
959
+ return null;
960
+ };
961
+ var TokenRefresher = () => {
962
+ useTokenRefresher();
963
+ return null;
964
+ };
965
+ var AuthProvider = ({
966
+ children,
967
+ baseURL,
968
+ queryClient
969
+ }) => {
970
+ const axiosConfig = {
971
+ headers: {
972
+ "Content-Type": "application/json"
973
+ }
974
+ };
975
+ return /* @__PURE__ */ jsxs(
976
+ AuthenticationProvider,
977
+ {
978
+ axiosConfig,
979
+ baseURL,
980
+ queryClient,
981
+ children: [
982
+ /* @__PURE__ */ jsx2(AuthStateManager, {}),
983
+ /* @__PURE__ */ jsx2(TokenRefresher, {}),
984
+ children
985
+ ]
986
+ }
987
+ );
988
+ };
989
+
990
+ // src/modules/auth/hooks/useGoogleLogin.ts
991
+ import { useRef, useCallback, useEffect as useEffect2 } from "react";
992
+ import { tokenStorage as tokenStorage4 } from "@phygitallabs/authentication";
993
+ function useGoogleLogin(options = {}) {
994
+ const { onSuccess, onError, onPopupBlocked, onPopupClosed } = options;
995
+ const { signInWithGoogle, refreshToken, setIsSignedIn, setIsLoading, isLoading } = useAuth();
996
+ const popupRef = useRef(null);
997
+ const gotDataRef = useRef(false);
998
+ const timerRef = useRef(null);
999
+ const errorRef = useRef(null);
1000
+ const handleTokenRefresh = useCallback(
1001
+ async (refresh) => {
1002
+ if (refresh) {
1003
+ try {
1004
+ const newToken = await refreshToken(refresh);
1005
+ if (newToken.data?.idToken && newToken.data?.refreshToken) {
1006
+ tokenStorage4.setTokens({
1007
+ idToken: newToken.data.idToken,
1008
+ refreshToken: newToken.data.refreshToken
1009
+ });
1010
+ setIsSignedIn(true);
1011
+ setIsLoading(false);
1012
+ onSuccess?.();
1013
+ }
1014
+ } catch (error) {
1015
+ const errorMessage = error instanceof Error ? error.message : "Token refresh failed";
1016
+ errorRef.current = errorMessage;
1017
+ onError?.(errorMessage);
1018
+ setIsLoading(false);
1019
+ }
1020
+ }
1021
+ },
1022
+ [refreshToken, setIsSignedIn, setIsLoading, onSuccess, onError]
1023
+ );
1024
+ const cleanup = useCallback(() => {
1025
+ if (timerRef.current) {
1026
+ clearInterval(timerRef.current);
1027
+ timerRef.current = null;
1028
+ }
1029
+ gotDataRef.current = false;
1030
+ }, []);
1031
+ const handleMessage = useCallback(
1032
+ (event) => {
1033
+ const allowedOrigins = ALLOWED_ORIGINS.concat(window?.location?.origin);
1034
+ if (event.origin !== "*" && !allowedOrigins.includes(event.origin)) {
1035
+ console.warn("Rejected message from untrusted origin:", event.origin);
1036
+ return;
1037
+ }
1038
+ if (!event.data || typeof event.data !== "object") {
1039
+ console.warn("Invalid message data received");
1040
+ return;
1041
+ }
1042
+ if (event.data.type === "LOGIN_SUCCESS") {
1043
+ const { refreshToken: refresh } = event.data;
1044
+ if (refresh) {
1045
+ handleTokenRefresh(refresh);
1046
+ }
1047
+ gotDataRef.current = true;
1048
+ cleanup();
1049
+ } else if (event.data.type === "LOGIN_ERROR") {
1050
+ const errorMessage = event.data.error || "Login failed";
1051
+ errorRef.current = errorMessage;
1052
+ onError?.(errorMessage);
1053
+ setIsLoading(false);
1054
+ gotDataRef.current = true;
1055
+ cleanup();
1056
+ }
1057
+ },
1058
+ [handleTokenRefresh, setIsLoading, cleanup, onError]
1059
+ );
1060
+ const signIn = useCallback(async () => {
1061
+ const width = 500;
1062
+ const height = 600;
1063
+ const left = window.screenX + (window.outerWidth - width) / 2;
1064
+ const top = window.screenY + (window.outerHeight - height) / 2;
1065
+ try {
1066
+ errorRef.current = null;
1067
+ setIsLoading(true);
1068
+ const response = await signInWithGoogle();
1069
+ popupRef.current = window.open(
1070
+ `${response.statusMessage}`,
1071
+ "oauthPopup",
1072
+ `width=${width},height=${height},left=${left},top=${top},resizable,scrollbars`
707
1073
  );
708
- const data = await response.json();
709
- if (data.error) {
710
- removeUserInfo();
1074
+ if (!popupRef.current) {
1075
+ setIsLoading(false);
1076
+ const error = "Popup blocked. Please allow popups for this site.";
1077
+ errorRef.current = error;
1078
+ onPopupBlocked?.();
1079
+ onError?.(error);
711
1080
  return;
712
1081
  }
713
- const newSession = {
714
- ...session,
715
- accessToken: data.access_token,
716
- refreshToken: data.refresh_token
717
- };
718
- setUserInfo(newSession);
719
- return newSession;
720
- } catch {
721
- removeUserInfo();
1082
+ timerRef.current = setInterval(() => {
1083
+ if (popupRef.current && popupRef.current.closed) {
1084
+ if (timerRef.current) {
1085
+ clearInterval(timerRef.current);
1086
+ timerRef.current = null;
1087
+ }
1088
+ if (!gotDataRef.current) {
1089
+ const error = "Authentication popup was closed";
1090
+ errorRef.current = error;
1091
+ onPopupClosed?.();
1092
+ onError?.(error);
1093
+ setIsLoading(false);
1094
+ }
1095
+ }
1096
+ }, 500);
1097
+ } catch (error) {
1098
+ const errorMessage = error instanceof Error ? error.message : "Google sign in failed";
1099
+ errorRef.current = errorMessage;
1100
+ onError?.(errorMessage);
1101
+ setIsLoading(false);
722
1102
  }
1103
+ }, [signInWithGoogle, setIsLoading, handleMessage, onError, onPopupBlocked, onPopupClosed]);
1104
+ useEffect2(() => {
1105
+ window.addEventListener("message", handleMessage);
1106
+ return () => {
1107
+ window.removeEventListener("message", handleMessage);
1108
+ };
1109
+ }, [handleMessage]);
1110
+ useEffect2(() => {
1111
+ return () => {
1112
+ cleanup();
1113
+ };
1114
+ }, [cleanup, handleMessage]);
1115
+ return {
1116
+ signIn,
1117
+ isLoading,
1118
+ error: errorRef.current
723
1119
  };
724
- return mem(refreshTokenFn, { maxAge: REFRESH_TOKEN_CONFIG.maxAge });
725
- };
1120
+ }
726
1121
 
727
1122
  // src/modules/auth/helpers/index.ts
1123
+ import { v4 as uuidv4 } from "uuid";
728
1124
  var generateDeviceId = async () => {
729
1125
  try {
730
1126
  const deviceFingerprint = await generateDeviceFingerprint();
@@ -839,208 +1235,6 @@ var removeUserInfo = () => {
839
1235
  localStorage.removeItem(userInfoKey);
840
1236
  };
841
1237
 
842
- // src/modules/auth/store/authSlice.ts
843
- var defaultUser = {
844
- uid: "",
845
- id: "",
846
- userName: "",
847
- displayName: "",
848
- avatar: "/images/default-avatar.jpg",
849
- email: "",
850
- exp: 0,
851
- emailVerified: false,
852
- refreshToken: "",
853
- accessToken: "",
854
- role: "NULL" /* NULL */,
855
- scanStatus: false
856
- };
857
- var initialState = {
858
- user: defaultUser,
859
- isSignedIn: false,
860
- pending: true
861
- };
862
- var authSlice = createSlice({
863
- name: "auth",
864
- initialState,
865
- reducers: {
866
- signIn: (state, action) => {
867
- const userData = action.payload;
868
- state.user = userData;
869
- state.isSignedIn = true;
870
- state.pending = false;
871
- setUserInfo(userData);
872
- setAccessToken(userData.accessToken);
873
- setRefreshToken(userData.refreshToken);
874
- },
875
- signOut: (state) => {
876
- state.user = defaultUser;
877
- state.isSignedIn = false;
878
- state.pending = false;
879
- removeUserInfo();
880
- removeAccessToken();
881
- removeRefreshToken();
882
- },
883
- updateScanStatus: (state, action) => {
884
- state.user.scanStatus = action.payload;
885
- setUserInfo(state.user);
886
- },
887
- refreshUser: (state, action) => {
888
- const userData = action.payload;
889
- if (userData) {
890
- state.user = userData;
891
- state.isSignedIn = true;
892
- state.pending = false;
893
- setUserInfo(userData);
894
- setAccessToken(userData.accessToken);
895
- setRefreshToken(userData.refreshToken);
896
- }
897
- },
898
- setPending: (state, action) => {
899
- state.pending = action.payload;
900
- },
901
- initializeFromStorage: (state) => {
902
- const storedUser = getUserInfo();
903
- const accessToken = getAccessToken();
904
- if (storedUser && accessToken) {
905
- state.user = storedUser;
906
- state.isSignedIn = true;
907
- }
908
- state.pending = false;
909
- }
910
- }
911
- });
912
- var {
913
- signIn,
914
- signOut,
915
- updateScanStatus,
916
- refreshUser,
917
- setPending,
918
- initializeFromStorage
919
- } = authSlice.actions;
920
- var selectUser = (state) => state.auth.user;
921
- var selectIsSignedIn = (state) => state.auth.isSignedIn;
922
- var selectIsLoading = (state) => state.auth.pending;
923
- var authSlice_default = authSlice.reducer;
924
-
925
- // src/modules/auth/providers/AuthProvider.tsx
926
- import { jsx as jsx2 } from "react/jsx-runtime";
927
- var AuthContext = createContext(null);
928
- function AuthProvider({ children, authService, authCallbacks }) {
929
- const dispatch = useAppDispatch();
930
- useEffect(() => {
931
- dispatch(initializeFromStorage());
932
- const unsubscribe = authService.onAuthStateChanged((user2) => {
933
- if (user2) {
934
- dispatch(signIn(user2));
935
- if (authCallbacks?.onUserIdentify && user2.email) {
936
- authCallbacks.onUserIdentify({
937
- email: user2.email,
938
- name: user2.displayName,
939
- avatar: user2.avatar,
940
- uid: user2.uid
941
- });
942
- }
943
- if (authCallbacks?.onSignInSuccess) {
944
- authCallbacks.onSignInSuccess(user2);
945
- }
946
- } else {
947
- dispatch(signOut());
948
- if (authCallbacks?.onTrackingReset) {
949
- authCallbacks.onTrackingReset();
950
- }
951
- }
952
- dispatch(setPending(false));
953
- });
954
- return () => {
955
- unsubscribe();
956
- };
957
- }, [authService, dispatch, authCallbacks]);
958
- const user = useAppSelector(selectUser);
959
- const isSignedIn = useAppSelector(selectIsSignedIn);
960
- const isLoading = useAppSelector(selectIsLoading);
961
- const signInWithCredential = async (email, password) => {
962
- const result = await authService.signInWithEmailAndPassword(email, password);
963
- if (result.data && authCallbacks?.onSignInSuccess) {
964
- authCallbacks.onSignInSuccess(result.data);
965
- } else if (result.errorCode && authCallbacks?.onSignInError) {
966
- authCallbacks.onSignInError(result.errorCode);
967
- }
968
- return result;
969
- };
970
- const signInWithGoogle = async () => {
971
- const result = await authService.signInWithGoogle();
972
- if (result.data && authCallbacks?.onSignInSuccess) {
973
- authCallbacks.onSignInSuccess(result.data);
974
- return result;
975
- } else if (result.errorCode && authCallbacks?.onSignInError) {
976
- authCallbacks.onSignInError(result.errorCode);
977
- }
978
- return null;
979
- };
980
- const signUp = async (email, password) => {
981
- const result = await authService.signUp(email, password);
982
- if (result.data && authCallbacks?.onSignUpSuccess) {
983
- authCallbacks.onSignUpSuccess(result.data);
984
- } else if (result.errorCode && authCallbacks?.onSignUpError) {
985
- authCallbacks.onSignUpError(result.errorCode);
986
- }
987
- return result;
988
- };
989
- const signOut2 = async () => {
990
- await authService.signOut();
991
- dispatch(signOut());
992
- if (authCallbacks?.onSignOutSuccess) {
993
- authCallbacks.onSignOutSuccess();
994
- }
995
- };
996
- const forgotPassword = async (email) => {
997
- return await authService.sendPasswordResetEmail(email);
998
- };
999
- const sendEmailVerification = async () => {
1000
- return await authService.sendEmailVerification();
1001
- };
1002
- const changePassword = async (newPassword) => {
1003
- return await authService.changePassword(newPassword);
1004
- };
1005
- const updateScanStatus2 = (status) => {
1006
- dispatch(updateScanStatus(status));
1007
- };
1008
- const refreshUser2 = (userData) => {
1009
- dispatch(refreshUser(userData));
1010
- };
1011
- const contextValue = {
1012
- authService,
1013
- authCallbacks,
1014
- // User state
1015
- user,
1016
- isSignedIn,
1017
- isLoading,
1018
- // Auth actions
1019
- signInWithCredential,
1020
- signInWithGoogle,
1021
- signUp,
1022
- signOut: signOut2,
1023
- // Password actions
1024
- forgotPassword,
1025
- sendEmailVerification,
1026
- changePassword,
1027
- // User management
1028
- updateScanStatus: updateScanStatus2,
1029
- refreshUser: refreshUser2
1030
- };
1031
- return /* @__PURE__ */ jsx2(AuthContext.Provider, { value: contextValue, children });
1032
- }
1033
- var useAuth = () => {
1034
- const authContext = useContext(AuthContext);
1035
- if (!authContext) {
1036
- throw new Error("useAuth must be used within an AuthProvider");
1037
- }
1038
- return authContext;
1039
- };
1040
-
1041
- // src/modules/auth/index.ts
1042
- init_constants();
1043
-
1044
1238
  // src/modules/user-profile/hooks/index.ts
1045
1239
  import { useMyProfile, useUpdateMyProfile, useSyncCheckin, useCancelUserRewardsRequest } from "@phygitallabs/api-core";
1046
1240
 
@@ -1048,12 +1242,12 @@ import { useMyProfile, useUpdateMyProfile, useSyncCheckin, useCancelUserRewardsR
1048
1242
  import { UserSourceType } from "@phygitallabs/api-core";
1049
1243
 
1050
1244
  // src/modules/scan-chip/hooks/index.tsx
1051
- import { useEffect as useEffect2 } from "react";
1245
+ import { useEffect as useEffect3 } from "react";
1052
1246
  import { useChipScanStory } from "@phygitallabs/api-core";
1053
- import { usePGLCoreService } from "@phygitallabs/api-core";
1247
+ import { usePGLCoreService as usePGLCoreService2 } from "@phygitallabs/api-core";
1054
1248
  function useScanChip({ token, id, onScanChipError }) {
1055
- const { updateHeaders } = usePGLCoreService();
1056
- useEffect2(() => {
1249
+ const { updateHeaders } = usePGLCoreService2();
1250
+ useEffect3(() => {
1057
1251
  if (!!token) {
1058
1252
  const header = {
1059
1253
  "Chip-Authorization": token
@@ -1066,7 +1260,7 @@ function useScanChip({ token, id, onScanChipError }) {
1066
1260
  token,
1067
1261
  id
1068
1262
  });
1069
- useEffect2(() => {
1263
+ useEffect3(() => {
1070
1264
  if (isError) {
1071
1265
  onScanChipError?.();
1072
1266
  }
@@ -1139,11 +1333,172 @@ var filterLocationsByProperty = (locations, propertyName, value) => {
1139
1333
  import {
1140
1334
  useGenerateThaocamvienCertificate,
1141
1335
  useGenerateTemplateCertificate,
1142
- useGenerateFansipanCertificate
1336
+ useGenerateFansipanCertificate,
1337
+ useCreateCertificate,
1338
+ useCreateCertificateAnonymous,
1339
+ useCreateCertificateWithMask
1143
1340
  } from "@phygitallabs/generate-certificate";
1144
1341
 
1342
+ // src/modules/generate-certificate/helpers/index.ts
1343
+ import { wrapTextWithFont } from "@phygitallabs/generate-certificate";
1344
+
1145
1345
  // src/modules/data-tracking/hooks/index.ts
1146
1346
  import posthog from "posthog-js";
1347
+
1348
+ // src/modules/session-replay/providers/SessionReplayProvider.tsx
1349
+ import { createContext, useEffect as useEffect4, useReducer } from "react";
1350
+ import { v4 as uuidV4 } from "uuid";
1351
+
1352
+ // src/modules/session-replay/utils/index.ts
1353
+ var isBrowser = () => {
1354
+ return typeof window !== "undefined";
1355
+ };
1356
+
1357
+ // src/modules/session-replay/providers/SessionReplayProvider.tsx
1358
+ import { jsx as jsx3 } from "react/jsx-runtime";
1359
+ var TrackerContext = createContext(null);
1360
+ function defaultGetUserId() {
1361
+ return uuidV4();
1362
+ }
1363
+ async function newTracker(config) {
1364
+ try {
1365
+ const OpenReplay = (await import("@openreplay/tracker")).default;
1366
+ const getUserId = config?.userIdEnabled && config?.getUserId ? config.getUserId : defaultGetUserId;
1367
+ const trackerConfig = {
1368
+ projectKey: config?.projectKey || process.env.NEXT_PUBLIC_OPENREPLAY_PROJECT_KEY,
1369
+ ingestPoint: config?.ingestPoint,
1370
+ // Capture options
1371
+ captureExceptions: config.captureExceptions ?? true,
1372
+ capturePerformance: config.capturePerformance ?? true,
1373
+ // Network tracking
1374
+ network: config.network || {
1375
+ capturePayload: true,
1376
+ sanitizer: (data) => data
1377
+ },
1378
+ // Console tracking
1379
+ console: config.console || {
1380
+ levels: ["error", "warn", "log"]
1381
+ },
1382
+ // Privacy settings
1383
+ obscureTextEmails: config.obscureTextEmails ?? true,
1384
+ obscureTextNumbers: config.obscureTextNumbers ?? false,
1385
+ obscureInputEmails: config.obscureInputEmails ?? true,
1386
+ // Development mode
1387
+ __DISABLE_SECURE_MODE: config.__DISABLE_SECURE_MODE ?? (typeof process !== "undefined" && process.env?.NODE_ENV === "development")
1388
+ };
1389
+ const tracker = new OpenReplay(trackerConfig);
1390
+ if (config?.userIdEnabled) {
1391
+ const userId = getUserId();
1392
+ tracker.setUserID(userId);
1393
+ console.log("User ID set:", userId);
1394
+ }
1395
+ console.log("OpenReplay tracker initialized");
1396
+ console.log("Project Key:", trackerConfig.projectKey);
1397
+ console.log("Ingest Point:", trackerConfig.ingestPoint);
1398
+ return tracker;
1399
+ } catch (error) {
1400
+ console.error("Failed to create tracker:", error);
1401
+ throw error;
1402
+ }
1403
+ }
1404
+ function reducer(state, action) {
1405
+ const { debug = false } = state.config;
1406
+ switch (action.type) {
1407
+ case "init":
1408
+ if (!state.tracker && isBrowser()) {
1409
+ if (!state.config.projectKey && !process.env.NEXT_PUBLIC_OPENREPLAY_PROJECT_KEY) {
1410
+ console.warn(
1411
+ debug,
1412
+ "Project key not found. Skipping session replay initialization."
1413
+ );
1414
+ return state;
1415
+ }
1416
+ return {
1417
+ ...state,
1418
+ tracker: newTracker(state.config)
1419
+ };
1420
+ }
1421
+ return state;
1422
+ case "start":
1423
+ if (state.tracker) {
1424
+ Promise.resolve(state.tracker).then((tracker) => {
1425
+ tracker.start();
1426
+ console.log(debug, "Session replay tracker started");
1427
+ }).catch((error) => {
1428
+ console.error("Failed to start tracker:", error);
1429
+ });
1430
+ } else {
1431
+ console.warn(debug, "Tracker not initialized. Call initTracker() first.");
1432
+ }
1433
+ return state;
1434
+ case "setUserId":
1435
+ if (state.tracker) {
1436
+ Promise.resolve(state.tracker).then((tracker) => {
1437
+ tracker.setUserID(action.payload);
1438
+ console.log(debug, "User ID updated:", action.payload);
1439
+ }).catch((error) => {
1440
+ console.error("Failed to set user ID:", error);
1441
+ });
1442
+ } else {
1443
+ console.warn(debug, "Tracker not initialized. Call initTracker() first.");
1444
+ }
1445
+ return state;
1446
+ // Set metadata
1447
+ case "setMetadata":
1448
+ if (state.tracker) {
1449
+ Promise.resolve(state.tracker).then((tracker) => {
1450
+ Object.entries(action.payload || {})?.forEach(([key, value]) => {
1451
+ tracker.setMetadata(key, value);
1452
+ });
1453
+ console.log(debug, "Metadata updated:", action.payload.metadata);
1454
+ }).catch((error) => {
1455
+ console.error("Failed to set metadata:", error);
1456
+ });
1457
+ } else {
1458
+ console.warn(debug, "Tracker not initialized. Call initTracker() first.");
1459
+ }
1460
+ return state;
1461
+ default:
1462
+ return state;
1463
+ }
1464
+ }
1465
+ var SessionReplayProvider = ({
1466
+ children,
1467
+ config = {}
1468
+ }) => {
1469
+ const [, dispatch] = useReducer(reducer, {
1470
+ tracker: null,
1471
+ config
1472
+ });
1473
+ const initTracker = () => dispatch({ type: "init" });
1474
+ const startTracking = () => dispatch({ type: "start" });
1475
+ const setUserId = (userId) => dispatch({ type: "setUserId", payload: userId });
1476
+ const setMetadata = (metadata) => dispatch({ type: "setMetadata", payload: metadata });
1477
+ useEffect4(() => {
1478
+ initTracker();
1479
+ startTracking();
1480
+ }, []);
1481
+ return /* @__PURE__ */ jsx3(TrackerContext.Provider, { value: {
1482
+ initTracker,
1483
+ startTracking,
1484
+ setUserId,
1485
+ setMetadata
1486
+ }, children });
1487
+ };
1488
+
1489
+ // src/modules/session-replay/hooks/useSessionReplay.ts
1490
+ import { useContext } from "react";
1491
+ function useSessionReplay() {
1492
+ const context = useContext(TrackerContext);
1493
+ if (!context) {
1494
+ throw new Error(
1495
+ "useSessionReplay must be used within a SessionReplayProvider. Make sure your component is wrapped with <SessionReplayProvider>."
1496
+ );
1497
+ }
1498
+ return context;
1499
+ }
1500
+
1501
+ // src/modules/data-tracking/hooks/index.ts
1147
1502
  var pushEventToDataLayer = (event, data) => {
1148
1503
  try {
1149
1504
  window.dataLayer = window.dataLayer || [];
@@ -1166,6 +1521,7 @@ var pushEventToPosthog = (eventName, eventData) => {
1166
1521
  posthog.capture(eventName, eventData);
1167
1522
  };
1168
1523
  function useDataTracking() {
1524
+ const { setUserId, setMetadata } = useSessionReplay();
1169
1525
  const trackEvent = (eventName, eventData, useTools) => {
1170
1526
  useTools = useTools || ["gtm"];
1171
1527
  if (useTools.includes("gtm") && typeof window !== "undefined") {
@@ -1178,91 +1534,58 @@ function useDataTracking() {
1178
1534
  pushEventToPosthog(eventName, eventData);
1179
1535
  }
1180
1536
  };
1537
+ const trackUserIdentify = (userInfo) => {
1538
+ posthog.identify(userInfo.email, {
1539
+ email: userInfo.email,
1540
+ name: userInfo.name,
1541
+ avatar: userInfo.avatar,
1542
+ uid: userInfo.uid
1543
+ });
1544
+ setUserId(userInfo.id);
1545
+ setMetadata({
1546
+ user_email: userInfo.email
1547
+ });
1548
+ };
1549
+ const trackLogoutEvent = () => {
1550
+ posthog.capture("user_signed_out");
1551
+ };
1181
1552
  return {
1182
- trackEvent
1553
+ trackEvent,
1554
+ trackUserIdentify,
1555
+ trackLogoutEvent
1183
1556
  };
1184
1557
  }
1185
1558
 
1186
1559
  // src/providers/TapquestCoreProvider.tsx
1187
- import { useMemo as useMemo2 } from "react";
1188
- import { Provider } from "react-redux";
1189
- import { PersistGate } from "redux-persist/integration/react";
1560
+ import { useMemo } from "react";
1190
1561
 
1191
1562
  // src/providers/ServicesProvider.tsx
1192
- import { useEffect as useEffect3, useState, useMemo } from "react";
1563
+ import { useEffect as useEffect5, useState } from "react";
1193
1564
  import { PGLCoreServiceProvider } from "@phygitallabs/api-core";
1194
1565
  import { RewardServiceProvider } from "@phygitallabs/reward";
1195
1566
  import { AchievementServiceProvider as AchievementServiceProvider2 } from "@phygitallabs/achievement";
1196
1567
  import { GenerateCertificateServiceProvider } from "@phygitallabs/generate-certificate";
1197
- import axios from "axios";
1198
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
1568
+ import { Fragment, jsx as jsx4 } from "react/jsx-runtime";
1199
1569
  var ServicesProvider = ({
1200
1570
  children,
1201
1571
  queryClient,
1202
1572
  apiConfig = {
1203
1573
  environment: "dev",
1204
1574
  version: "v1"
1205
- },
1206
- firebaseConfig
1575
+ }
1207
1576
  }) => {
1208
- const { refreshUser: refreshUser2, signOut: signOut2 } = useAuth();
1209
1577
  const { environment, version } = apiConfig;
1210
1578
  const [commonServiceConfig, setCommonServiceConfig] = useState(null);
1211
- const memoizedRefreshToken = useMemo(() => {
1212
- if (!firebaseConfig?.apiKey) {
1213
- console.warn("Firebase API key not provided, refresh token functionality will not work");
1214
- return null;
1215
- }
1216
- return createRefreshTokenFunction({
1217
- firebaseApiKey: firebaseConfig.apiKey
1218
- });
1219
- }, [firebaseConfig?.apiKey]);
1220
- useEffect3(() => {
1579
+ useEffect5(() => {
1221
1580
  const initClient = async () => {
1222
1581
  try {
1223
1582
  const deviceUid = await checkDeviceUid();
1224
1583
  const responseInterceptors = {
1225
1584
  onFulfilled: (response) => response,
1226
- onRejected: async (error) => {
1227
- const originalRequest = error.config;
1228
- if (error.response?.status === 401 && !originalRequest._retry) {
1229
- const retryAttempts = parseInt(
1230
- getRetryAttemptsRefreshToken() || "0",
1231
- 10
1232
- );
1233
- if (retryAttempts >= httpMaxRetries) {
1234
- await signOut2();
1235
- return Promise.reject(error);
1236
- }
1237
- setRetryAttemptsRefreshToken(`${retryAttempts + 1}`);
1238
- originalRequest._retry = true;
1239
- try {
1240
- if (!memoizedRefreshToken) {
1241
- await signOut2();
1242
- return Promise.reject(error);
1243
- }
1244
- const result = await memoizedRefreshToken();
1245
- if (result?.accessToken) {
1246
- originalRequest.headers["Authorization"] = `Bearer ${result.accessToken}`;
1247
- setRetryAttemptsRefreshToken("0");
1248
- refreshUser2(result);
1249
- return axios(originalRequest);
1250
- }
1251
- } catch (refreshError) {
1252
- console.log("Failed to refresh token:", refreshError);
1253
- }
1254
- }
1255
- return Promise.reject(error);
1256
- }
1585
+ onRejected: async (error) => Promise.reject(error)
1257
1586
  };
1258
1587
  const requestInterceptors = {
1259
- onFulfilled: (config2) => {
1260
- const currentToken = getAccessToken();
1261
- if (currentToken && !config2.headers.Authorization) {
1262
- config2.headers.Authorization = `Bearer ${currentToken}`;
1263
- }
1264
- return config2;
1265
- },
1588
+ onFulfilled: (config2) => config2,
1266
1589
  onRejected: (error) => Promise.reject(error)
1267
1590
  };
1268
1591
  const axiosConfig = {
@@ -1286,25 +1609,25 @@ var ServicesProvider = ({
1286
1609
  initClient();
1287
1610
  }, [queryClient]);
1288
1611
  if (!commonServiceConfig) {
1289
- return /* @__PURE__ */ jsx3(Fragment, {});
1612
+ return /* @__PURE__ */ jsx4(Fragment, {});
1290
1613
  }
1291
- return /* @__PURE__ */ jsx3(
1614
+ return /* @__PURE__ */ jsx4(
1292
1615
  PGLCoreServiceProvider,
1293
1616
  {
1294
1617
  ...commonServiceConfig,
1295
1618
  baseURL: `${service_default[environment].API_BASE_URL}/${version}`,
1296
1619
  baseCoreURL: `${service_default[environment].API_BASE_CORE_URL}/${version}`,
1297
- children: /* @__PURE__ */ jsx3(
1620
+ children: /* @__PURE__ */ jsx4(
1298
1621
  RewardServiceProvider,
1299
1622
  {
1300
1623
  ...commonServiceConfig,
1301
1624
  baseURL: `${service_default[environment].API_REWARD_URL}/v1`,
1302
- children: /* @__PURE__ */ jsx3(
1625
+ children: /* @__PURE__ */ jsx4(
1303
1626
  AchievementServiceProvider2,
1304
1627
  {
1305
1628
  ...commonServiceConfig,
1306
1629
  baseURL: `${service_default[environment].API_ACHIEVEMENT_URL}/${version}`,
1307
- children: /* @__PURE__ */ jsx3(
1630
+ children: /* @__PURE__ */ jsx4(
1308
1631
  GenerateCertificateServiceProvider,
1309
1632
  {
1310
1633
  ...commonServiceConfig,
@@ -1320,80 +1643,51 @@ var ServicesProvider = ({
1320
1643
  );
1321
1644
  };
1322
1645
 
1323
- // src/store/index.ts
1324
- import { configureStore } from "@reduxjs/toolkit";
1325
- import storage from "redux-persist/lib/storage";
1326
- import { persistReducer, persistStore } from "redux-persist";
1327
- var authPersistConfig = {
1328
- key: "tapquest-auth",
1329
- storage,
1330
- whitelist: ["user", "isSignedIn"]
1331
- // Only persist user and sign-in status
1332
- };
1333
- var persistedAuthReducer = persistReducer(authPersistConfig, authSlice.reducer);
1334
- var store = configureStore({
1335
- reducer: {
1336
- auth: persistedAuthReducer
1337
- },
1338
- middleware: (getDefaultMiddleware) => getDefaultMiddleware({
1339
- serializableCheck: {
1340
- // Ignore redux-persist actions
1341
- ignoredActions: [
1342
- "persist/FLUSH",
1343
- "persist/REHYDRATE",
1344
- "persist/PAUSE",
1345
- "persist/PERSIST",
1346
- "persist/PURGE",
1347
- "persist/REGISTER"
1348
- ]
1349
- }
1350
- })
1351
- });
1352
- var persistor = persistStore(store);
1353
-
1354
1646
  // src/providers/TapquestCoreProvider.tsx
1355
- import { jsx as jsx4 } from "react/jsx-runtime";
1647
+ import { jsx as jsx5 } from "react/jsx-runtime";
1356
1648
  var TapquestCoreProvider = ({
1357
1649
  children,
1358
1650
  queryClient,
1359
- apiConfig,
1360
- firebaseConfig,
1361
- authCallbacks
1651
+ apiConfig
1652
+ // authCallbacks
1362
1653
  }) => {
1363
- const internalAuthService = useMemo2(() => {
1364
- if (firebaseConfig && typeof window !== "undefined") {
1365
- try {
1366
- const { createAuthService: createAuthService2 } = (init_services(), __toCommonJS(services_exports));
1367
- return createAuthService2({ firebaseConfig });
1368
- } catch (error) {
1369
- console.warn("Failed to create auth service from firebase config:", error);
1370
- return null;
1371
- }
1654
+ const { environment } = apiConfig;
1655
+ const sessionReplayConfig = useMemo(() => {
1656
+ const projectKey = process.env.NEXT_PUBLIC_OPENREPLAY_PROJECT_KEY;
1657
+ if (!projectKey) {
1658
+ return void 0;
1372
1659
  }
1373
- return null;
1374
- }, [firebaseConfig]);
1375
- return /* @__PURE__ */ jsx4(Provider, { store, children: /* @__PURE__ */ jsx4(PersistGate, { loading: null, persistor, children: /* @__PURE__ */ jsx4(
1376
- AuthProvider,
1660
+ return {
1661
+ projectKey,
1662
+ ingestPoint: process.env.NEXT_PUBLIC_OPENREPLAY_INGEST_POINT,
1663
+ debug: process.env.NODE_ENV === "development",
1664
+ captureExceptions: true,
1665
+ capturePerformance: true,
1666
+ obscureTextEmails: true,
1667
+ obscureInputEmails: true
1668
+ };
1669
+ }, []);
1670
+ return /* @__PURE__ */ jsx5(SessionReplayProvider, { config: sessionReplayConfig, children: /* @__PURE__ */ jsx5(
1671
+ ServicesProvider,
1377
1672
  {
1378
- authService: internalAuthService,
1379
- authCallbacks,
1380
- children: /* @__PURE__ */ jsx4(
1381
- ServicesProvider,
1673
+ queryClient,
1674
+ apiConfig,
1675
+ children: /* @__PURE__ */ jsx5(
1676
+ AuthProvider,
1382
1677
  {
1678
+ baseURL: `${service_default[environment].API_BASE_URL}`,
1383
1679
  queryClient,
1384
- apiConfig,
1385
- firebaseConfig,
1386
1680
  children
1387
1681
  }
1388
1682
  )
1389
1683
  }
1390
- ) }) });
1684
+ ) });
1391
1685
  };
1392
1686
 
1393
1687
  // src/modules/achivementWithReward/hooks/achivementPlusRewardModel.ts
1394
1688
  import { useManyAchievements as useManyAchievements2 } from "@phygitallabs/achievement";
1395
1689
  import { useCreateModelGroupReward as useCreateModelGroupReward2 } from "@phygitallabs/reward/src/hooks/useGroupReward";
1396
- import { useEffect as useEffect4, useMemo as useMemo3 } from "react";
1690
+ import { useEffect as useEffect6, useMemo as useMemo2 } from "react";
1397
1691
  function buildMappedAchievements(achievements, groupRewardData) {
1398
1692
  if (!groupRewardData?.reward_models) return [];
1399
1693
  const rewardModels = groupRewardData.reward_models;
@@ -1423,7 +1717,7 @@ var useAchivementPlusRewardModel = ({ campaignId }) => {
1423
1717
  },
1424
1718
  { enabled: !!campaignId }
1425
1719
  );
1426
- const groupRewardIds = useMemo3(() => {
1720
+ const groupRewardIds = useMemo2(() => {
1427
1721
  if (!achievements?.data) return [];
1428
1722
  return achievements.data.map((achievement) => achievement.groupRewardId).filter((id) => id !== void 0);
1429
1723
  }, [achievements?.data]);
@@ -1432,12 +1726,12 @@ var useAchivementPlusRewardModel = ({ campaignId }) => {
1432
1726
  data: groupRewardModelsData,
1433
1727
  isPending: isPendingGroupRewardModels
1434
1728
  } = useCreateModelGroupReward2();
1435
- useEffect4(() => {
1729
+ useEffect6(() => {
1436
1730
  if (groupRewardIds.length > 0) {
1437
1731
  fetchGroupRewardModels({ group_reward_ids: groupRewardIds });
1438
1732
  }
1439
1733
  }, [groupRewardIds, fetchGroupRewardModels]);
1440
- const mappedAchievements = useMemo3(() => {
1734
+ const mappedAchievements = useMemo2(() => {
1441
1735
  if (!groupRewardModelsData?.data || !achievements?.data) return [];
1442
1736
  return buildMappedAchievements(achievements.data, groupRewardModelsData.data);
1443
1737
  }, [groupRewardModelsData, achievements?.data]);
@@ -1454,10 +1748,12 @@ import { useSendEmail } from "@phygitallabs/api-core";
1454
1748
  // src/helper/helpers.ts
1455
1749
  import { cn, parse, fileToBase64 } from "@phygitallabs/helpers";
1456
1750
  export {
1751
+ ALLOWED_ORIGINS,
1457
1752
  AchievementRuleActionType,
1458
1753
  AchievementServiceProvider,
1459
1754
  AchievementType,
1460
1755
  AuthProvider,
1756
+ CALLBACK_URL,
1461
1757
  CampaignState,
1462
1758
  CmentityRewardType,
1463
1759
  NotificationProvider,
@@ -1470,7 +1766,6 @@ export {
1470
1766
  chipAuthTokenKey,
1471
1767
  cn,
1472
1768
  convertSnakeToCamel,
1473
- createRefreshTokenFunction,
1474
1769
  deviceUIDKey,
1475
1770
  fileToBase64,
1476
1771
  filterLocationsByProperty,
@@ -1511,18 +1806,22 @@ export {
1511
1806
  useChipScanStory,
1512
1807
  useClaimUserReward,
1513
1808
  useClearUserRewardCache,
1809
+ useCreateCertificate,
1810
+ useCreateCertificateAnonymous,
1811
+ useCreateCertificateWithMask,
1514
1812
  useCreateMemory,
1515
1813
  useCreateModelGroupReward,
1516
- useApiCreateRewardModel as useCreateRewardModel,
1814
+ useCreateRewardModel,
1517
1815
  useDataTracking,
1518
- useApiDeleteRewardModel as useDeleteRewardModel,
1816
+ useDeleteRewardModel,
1519
1817
  useGenerateFansipanCertificate,
1520
1818
  useGenerateTemplateCertificate,
1521
1819
  useGenerateThaocamvienCertificate,
1522
- useApiGetRewardModel as useGetRewardModel,
1820
+ useGetRewardModel,
1523
1821
  useGetUserRewards,
1822
+ useGoogleLogin,
1524
1823
  useInfiniteMemories,
1525
- useApiListRewardModels as useListRewardModels,
1824
+ useListRewardModels,
1526
1825
  useOneLocation as useLocationDetail,
1527
1826
  useUserCampaignsCompletedLocation as useLocationProgress,
1528
1827
  useManyLocations as useLocationsList,
@@ -1537,16 +1836,17 @@ export {
1537
1836
  useOneAchievement,
1538
1837
  useOneMemory,
1539
1838
  useOneUserCampaign,
1540
- usePGLCoreService,
1839
+ usePGLCoreService2 as usePGLCoreService,
1541
1840
  useScanChip,
1542
1841
  useSendEmail,
1543
1842
  useSyncCheckin,
1544
1843
  useUpdateMyProfile,
1545
- useApiUpdateRewardModel as useUpdateRewardModel,
1844
+ useUpdateRewardModel,
1546
1845
  useUploadMedia,
1547
1846
  useUserAchievementAction,
1548
1847
  useUserCampaignAction,
1549
1848
  useV1ListRewards,
1550
- userInfoKey
1849
+ userInfoKey,
1850
+ wrapTextWithFont
1551
1851
  };
1552
1852
  //# sourceMappingURL=index.js.map