@appgram/react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,758 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+
7
+ // src/provider/context.ts
8
+ var AppgramContext = react.createContext(null);
9
+ function useAppgramContext() {
10
+ const context = react.useContext(AppgramContext);
11
+ if (!context) {
12
+ throw new Error(
13
+ "useAppgramContext must be used within an AppgramProvider. Make sure you have wrapped your app with <AppgramProvider>."
14
+ );
15
+ }
16
+ return context;
17
+ }
18
+
19
+ // src/utils/fingerprint.ts
20
+ var STORAGE_KEY = "appgram_fingerprint";
21
+ function simpleHash(str) {
22
+ let hash = 0;
23
+ for (let i = 0; i < str.length; i++) {
24
+ const char = str.charCodeAt(i);
25
+ hash = (hash << 5) - hash + char;
26
+ hash = hash & hash;
27
+ }
28
+ return Math.abs(hash).toString(36);
29
+ }
30
+ function getBrowserCharacteristics() {
31
+ if (typeof window === "undefined") {
32
+ return "server-side";
33
+ }
34
+ const characteristics = [
35
+ navigator.userAgent,
36
+ navigator.language,
37
+ screen.colorDepth,
38
+ screen.width,
39
+ screen.height,
40
+ (/* @__PURE__ */ new Date()).getTimezoneOffset(),
41
+ navigator.hardwareConcurrency || 0,
42
+ "deviceMemory" in navigator ? navigator.deviceMemory : 0
43
+ ];
44
+ return characteristics.join("|");
45
+ }
46
+ function generateFingerprint() {
47
+ const characteristics = getBrowserCharacteristics();
48
+ const timestamp = Date.now().toString(36);
49
+ const randomBytes = new Uint8Array(6);
50
+ crypto.getRandomValues(randomBytes);
51
+ const random = Array.from(randomBytes, (b) => b.toString(36)).join("").substring(0, 10);
52
+ return `${simpleHash(characteristics)}-${timestamp}-${random}`;
53
+ }
54
+ function getFingerprint() {
55
+ if (typeof window === "undefined") {
56
+ return "server-side-fingerprint";
57
+ }
58
+ let fingerprint = localStorage.getItem(STORAGE_KEY);
59
+ if (!fingerprint) {
60
+ fingerprint = generateFingerprint();
61
+ try {
62
+ localStorage.setItem(STORAGE_KEY, fingerprint);
63
+ } catch {
64
+ }
65
+ }
66
+ return fingerprint;
67
+ }
68
+ function resetFingerprint() {
69
+ if (typeof window === "undefined") return;
70
+ try {
71
+ localStorage.removeItem(STORAGE_KEY);
72
+ } catch {
73
+ }
74
+ }
75
+ function cn(...inputs) {
76
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
77
+ }
78
+
79
+ // src/utils/index.ts
80
+ function getErrorMessage(error, fallback = "An error occurred") {
81
+ if (!error) return fallback;
82
+ if (typeof error === "string") return error;
83
+ if (typeof error === "object" && error !== null) {
84
+ if ("message" in error && typeof error.message === "string") {
85
+ return error.message;
86
+ }
87
+ }
88
+ return fallback;
89
+ }
90
+ function useWishes(options = {}) {
91
+ const { client, fingerprint } = useAppgramContext();
92
+ const [wishes, setWishes] = react.useState([]);
93
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
94
+ const [error, setError] = react.useState(null);
95
+ const [total, setTotal] = react.useState(0);
96
+ const [page, setPage] = react.useState(options.filters?.page || 1);
97
+ const [totalPages, setTotalPages] = react.useState(0);
98
+ const [filters, setFilters] = react.useState(options.filters || {});
99
+ const intervalRef = react.useRef(null);
100
+ const fetchWishes = react.useCallback(async () => {
101
+ if (options.skip) return;
102
+ setIsLoading(true);
103
+ setError(null);
104
+ try {
105
+ const response = await client.getPublicWishes({
106
+ ...filters,
107
+ page,
108
+ fingerprint: fingerprint ?? void 0
109
+ });
110
+ if (response.success && response.data) {
111
+ const wishData = response.data.data || [];
112
+ setWishes(wishData);
113
+ setTotal(response.data.total);
114
+ setTotalPages(response.data.total_pages);
115
+ } else {
116
+ setError(getErrorMessage(response.error, "Failed to fetch wishes"));
117
+ }
118
+ } catch (err) {
119
+ setError(getErrorMessage(err, "An error occurred"));
120
+ } finally {
121
+ setIsLoading(false);
122
+ }
123
+ }, [client, fingerprint, filters, page, options.skip]);
124
+ react.useEffect(() => {
125
+ fetchWishes();
126
+ }, [fetchWishes]);
127
+ react.useEffect(() => {
128
+ if (options.refreshInterval && options.refreshInterval > 0) {
129
+ intervalRef.current = setInterval(fetchWishes, options.refreshInterval);
130
+ }
131
+ return () => {
132
+ if (intervalRef.current) {
133
+ clearInterval(intervalRef.current);
134
+ }
135
+ };
136
+ }, [options.refreshInterval, fetchWishes]);
137
+ const handleSetFilters = react.useCallback((newFilters) => {
138
+ setFilters(newFilters);
139
+ setPage(1);
140
+ }, []);
141
+ return {
142
+ wishes,
143
+ isLoading,
144
+ error,
145
+ total,
146
+ page,
147
+ totalPages,
148
+ setFilters: handleSetFilters,
149
+ setPage,
150
+ refetch: fetchWishes
151
+ };
152
+ }
153
+ function useVote(options) {
154
+ const { client, fingerprint } = useAppgramContext();
155
+ const [hasVoted, setHasVoted] = react.useState(options.initialHasVoted || false);
156
+ const [voteCount, setVoteCount] = react.useState(options.initialVoteCount || 0);
157
+ const [voteId, setVoteId] = react.useState(null);
158
+ const [isLoading, setIsLoading] = react.useState(false);
159
+ const [isChecking, setIsChecking] = react.useState(false);
160
+ const [hasChecked, setHasChecked] = react.useState(false);
161
+ const [error, setError] = react.useState(null);
162
+ const skipAutoCheck = options.skipAutoCheck !== false;
163
+ const checkVoteStatus = react.useCallback(async () => {
164
+ if (!fingerprint || !options.wishId || hasChecked) {
165
+ return;
166
+ }
167
+ setIsChecking(true);
168
+ try {
169
+ const response = await client.checkVote(options.wishId, fingerprint);
170
+ if (response.success && response.data) {
171
+ setHasVoted(response.data.has_voted);
172
+ if (response.data.vote_id) {
173
+ setVoteId(response.data.vote_id);
174
+ }
175
+ }
176
+ setHasChecked(true);
177
+ } catch {
178
+ setHasChecked(true);
179
+ } finally {
180
+ setIsChecking(false);
181
+ }
182
+ }, [client, fingerprint, options.wishId, hasChecked]);
183
+ react.useEffect(() => {
184
+ if (!skipAutoCheck) {
185
+ checkVoteStatus();
186
+ }
187
+ }, [skipAutoCheck, checkVoteStatus]);
188
+ react.useEffect(() => {
189
+ if (options.initialVoteCount !== void 0) {
190
+ setVoteCount(options.initialVoteCount);
191
+ }
192
+ }, [options.initialVoteCount]);
193
+ react.useEffect(() => {
194
+ if (options.initialHasVoted !== void 0) {
195
+ setHasVoted(options.initialHasVoted);
196
+ }
197
+ }, [options.initialHasVoted]);
198
+ const vote = react.useCallback(async () => {
199
+ if (!fingerprint || isLoading) return;
200
+ if (!hasChecked) {
201
+ setIsLoading(true);
202
+ try {
203
+ const checkResponse = await client.checkVote(options.wishId, fingerprint);
204
+ if (checkResponse.success && checkResponse.data) {
205
+ setHasVoted(checkResponse.data.has_voted);
206
+ if (checkResponse.data.vote_id) {
207
+ setVoteId(checkResponse.data.vote_id);
208
+ }
209
+ setHasChecked(true);
210
+ if (checkResponse.data.has_voted) {
211
+ setIsLoading(false);
212
+ return;
213
+ }
214
+ }
215
+ } catch {
216
+ setHasChecked(true);
217
+ }
218
+ } else if (hasVoted) {
219
+ return;
220
+ }
221
+ setIsLoading(true);
222
+ setError(null);
223
+ try {
224
+ const response = await client.createVote(
225
+ options.wishId,
226
+ fingerprint,
227
+ options.voterEmail
228
+ );
229
+ if (response.success && response.data) {
230
+ setHasVoted(true);
231
+ setVoteId(response.data.id);
232
+ setVoteCount((prev) => prev + 1);
233
+ options.onVoteChange?.(true, voteCount + 1);
234
+ } else {
235
+ setError(getErrorMessage(response.error, "Failed to vote"));
236
+ }
237
+ } catch (err) {
238
+ setError(getErrorMessage(err, "Failed to vote"));
239
+ } finally {
240
+ setIsLoading(false);
241
+ }
242
+ }, [client, fingerprint, hasVoted, hasChecked, isLoading, options, voteCount]);
243
+ const unvote = react.useCallback(async () => {
244
+ if (!voteId || !hasVoted || isLoading) return;
245
+ setIsLoading(true);
246
+ setError(null);
247
+ try {
248
+ const response = await client.deleteVote(voteId);
249
+ if (response.success) {
250
+ setHasVoted(false);
251
+ setVoteId(null);
252
+ setVoteCount((prev) => Math.max(0, prev - 1));
253
+ options.onVoteChange?.(false, Math.max(0, voteCount - 1));
254
+ } else {
255
+ setError(getErrorMessage(response.error, "Failed to remove vote"));
256
+ }
257
+ } catch (err) {
258
+ setError(getErrorMessage(err, "Failed to remove vote"));
259
+ } finally {
260
+ setIsLoading(false);
261
+ }
262
+ }, [client, hasVoted, isLoading, options, voteCount, voteId]);
263
+ const toggle = react.useCallback(async () => {
264
+ if (!fingerprint || isLoading) return;
265
+ if (!hasChecked) {
266
+ setIsLoading(true);
267
+ try {
268
+ const checkResponse = await client.checkVote(options.wishId, fingerprint);
269
+ if (checkResponse.success && checkResponse.data) {
270
+ const alreadyVoted = checkResponse.data.has_voted;
271
+ setHasVoted(alreadyVoted);
272
+ if (checkResponse.data.vote_id) {
273
+ setVoteId(checkResponse.data.vote_id);
274
+ }
275
+ setHasChecked(true);
276
+ setIsLoading(false);
277
+ if (alreadyVoted) {
278
+ if (checkResponse.data.vote_id) {
279
+ await unvote();
280
+ }
281
+ } else {
282
+ await vote();
283
+ }
284
+ return;
285
+ }
286
+ } catch {
287
+ setHasChecked(true);
288
+ setIsLoading(false);
289
+ }
290
+ }
291
+ if (hasVoted) {
292
+ await unvote();
293
+ } else {
294
+ await vote();
295
+ }
296
+ }, [client, fingerprint, hasVoted, hasChecked, isLoading, options.wishId, unvote, vote]);
297
+ return {
298
+ hasVoted,
299
+ voteCount,
300
+ isLoading,
301
+ isChecking,
302
+ error,
303
+ toggle,
304
+ vote,
305
+ unvote
306
+ };
307
+ }
308
+ function useComments(options) {
309
+ const { client } = useAppgramContext();
310
+ const [comments, setComments] = react.useState([]);
311
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
312
+ const [isCreating, setIsCreating] = react.useState(false);
313
+ const [error, setError] = react.useState(null);
314
+ const [total, setTotal] = react.useState(0);
315
+ const [page, setPage] = react.useState(1);
316
+ const [totalPages, setTotalPages] = react.useState(0);
317
+ const perPage = options.perPage || 20;
318
+ const fetchComments = react.useCallback(async () => {
319
+ if (options.skip || !options.wishId) return;
320
+ setIsLoading(true);
321
+ setError(null);
322
+ try {
323
+ const response = await client.getComments(options.wishId, {
324
+ page,
325
+ per_page: perPage
326
+ });
327
+ if (response.success && response.data) {
328
+ setComments(response.data.data || []);
329
+ setTotal(response.data.total);
330
+ setTotalPages(response.data.total_pages);
331
+ } else {
332
+ setError(getErrorMessage(response.error, "Failed to fetch comments"));
333
+ }
334
+ } catch (err) {
335
+ setError(getErrorMessage(err, "An error occurred"));
336
+ } finally {
337
+ setIsLoading(false);
338
+ }
339
+ }, [client, options.wishId, options.skip, page, perPage]);
340
+ react.useEffect(() => {
341
+ fetchComments();
342
+ }, [fetchComments]);
343
+ const createComment = react.useCallback(
344
+ async (data) => {
345
+ setIsCreating(true);
346
+ setError(null);
347
+ try {
348
+ const response = await client.createComment({
349
+ ...data,
350
+ wish_id: options.wishId
351
+ });
352
+ if (response.success && response.data) {
353
+ setComments((prev) => [response.data, ...prev]);
354
+ setTotal((prev) => prev + 1);
355
+ return response.data;
356
+ } else {
357
+ setError(getErrorMessage(response.error, "Failed to create comment"));
358
+ return null;
359
+ }
360
+ } catch (err) {
361
+ setError(getErrorMessage(err, "An error occurred"));
362
+ return null;
363
+ } finally {
364
+ setIsCreating(false);
365
+ }
366
+ },
367
+ [client, options.wishId]
368
+ );
369
+ const nextPage = react.useCallback(() => {
370
+ if (page < totalPages) {
371
+ setPage((prev) => prev + 1);
372
+ }
373
+ }, [page, totalPages]);
374
+ const prevPage = react.useCallback(() => {
375
+ if (page > 1) {
376
+ setPage((prev) => prev - 1);
377
+ }
378
+ }, [page]);
379
+ return {
380
+ comments,
381
+ isLoading,
382
+ isCreating,
383
+ error,
384
+ total,
385
+ page,
386
+ totalPages,
387
+ nextPage,
388
+ prevPage,
389
+ setPage,
390
+ createComment,
391
+ refetch: fetchComments
392
+ };
393
+ }
394
+ function useRoadmap(options = {}) {
395
+ const { client } = useAppgramContext();
396
+ const [roadmap, setRoadmap] = react.useState(null);
397
+ const [columns, setColumns] = react.useState([]);
398
+ const [totalItems, setTotalItems] = react.useState(0);
399
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
400
+ const [error, setError] = react.useState(null);
401
+ const fetchRoadmap = react.useCallback(async () => {
402
+ if (options.skip) return;
403
+ setIsLoading(true);
404
+ setError(null);
405
+ try {
406
+ const response = await client.getRoadmapData();
407
+ if (response.success && response.data) {
408
+ setRoadmap(response.data.roadmap);
409
+ const cols = response.data.columns || response.data.roadmap?.columns || [];
410
+ setColumns(cols);
411
+ const itemCount = response.data.total_items || cols.reduce((sum, col) => sum + (col.items?.length || 0), 0);
412
+ setTotalItems(itemCount);
413
+ } else {
414
+ setError(getErrorMessage(response.error, "Failed to fetch roadmap"));
415
+ }
416
+ } catch (err) {
417
+ setError(getErrorMessage(err, "An error occurred"));
418
+ } finally {
419
+ setIsLoading(false);
420
+ }
421
+ }, [client, options.skip]);
422
+ react.useEffect(() => {
423
+ fetchRoadmap();
424
+ }, [fetchRoadmap]);
425
+ react.useEffect(() => {
426
+ if (!options.refreshInterval || options.refreshInterval <= 0) return;
427
+ const interval = setInterval(fetchRoadmap, options.refreshInterval);
428
+ return () => clearInterval(interval);
429
+ }, [options.refreshInterval, fetchRoadmap]);
430
+ return {
431
+ roadmap,
432
+ columns,
433
+ totalItems,
434
+ isLoading,
435
+ error,
436
+ refetch: fetchRoadmap
437
+ };
438
+ }
439
+ function useReleases(options = {}) {
440
+ const { client } = useAppgramContext();
441
+ const [releases, setReleases] = react.useState([]);
442
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
443
+ const [error, setError] = react.useState(null);
444
+ const fetchReleases = react.useCallback(async () => {
445
+ if (options.skip) return;
446
+ setIsLoading(true);
447
+ setError(null);
448
+ try {
449
+ const response = await client.getReleases({
450
+ limit: options.limit || 50
451
+ });
452
+ if (response.success && response.data) {
453
+ setReleases(response.data);
454
+ } else {
455
+ setError(getErrorMessage(response.error, "Failed to fetch releases"));
456
+ }
457
+ } catch (err) {
458
+ setError(getErrorMessage(err, "An error occurred"));
459
+ } finally {
460
+ setIsLoading(false);
461
+ }
462
+ }, [client, options.skip, options.limit]);
463
+ react.useEffect(() => {
464
+ fetchReleases();
465
+ }, [fetchReleases]);
466
+ return {
467
+ releases,
468
+ isLoading,
469
+ error,
470
+ refetch: fetchReleases
471
+ };
472
+ }
473
+ function useRelease(options) {
474
+ const { client } = useAppgramContext();
475
+ const [release, setRelease] = react.useState(null);
476
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
477
+ const [error, setError] = react.useState(null);
478
+ const fetchRelease = react.useCallback(async () => {
479
+ if (options.skip || !options.releaseSlug) return;
480
+ setIsLoading(true);
481
+ setError(null);
482
+ try {
483
+ const response = await client.getRelease(options.releaseSlug);
484
+ if (response.success && response.data) {
485
+ setRelease(response.data);
486
+ } else {
487
+ setError(getErrorMessage(response.error, "Failed to fetch release"));
488
+ }
489
+ } catch (err) {
490
+ setError(getErrorMessage(err, "An error occurred"));
491
+ } finally {
492
+ setIsLoading(false);
493
+ }
494
+ }, [client, options.skip, options.releaseSlug]);
495
+ react.useEffect(() => {
496
+ fetchRelease();
497
+ }, [fetchRelease]);
498
+ return {
499
+ release,
500
+ isLoading,
501
+ error,
502
+ refetch: fetchRelease
503
+ };
504
+ }
505
+ function useHelpCenter(options = {}) {
506
+ const { client } = useAppgramContext();
507
+ const [collection, setCollection] = react.useState(null);
508
+ const [flows, setFlows] = react.useState([]);
509
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
510
+ const [error, setError] = react.useState(null);
511
+ const fetchHelpCenter = react.useCallback(async () => {
512
+ if (options.skip) return;
513
+ setIsLoading(true);
514
+ setError(null);
515
+ try {
516
+ const response = await client.getHelpCollection();
517
+ if (response.success && response.data) {
518
+ setCollection(response.data.collection);
519
+ setFlows(response.data.flows || []);
520
+ } else {
521
+ setError(getErrorMessage(response.error, "Failed to fetch help center"));
522
+ }
523
+ } catch (err) {
524
+ setError(getErrorMessage(err, "An error occurred"));
525
+ } finally {
526
+ setIsLoading(false);
527
+ }
528
+ }, [client, options.skip]);
529
+ react.useEffect(() => {
530
+ fetchHelpCenter();
531
+ }, [fetchHelpCenter]);
532
+ return {
533
+ collection,
534
+ flows,
535
+ isLoading,
536
+ error,
537
+ refetch: fetchHelpCenter
538
+ };
539
+ }
540
+ function useHelpFlow(options) {
541
+ const { client } = useAppgramContext();
542
+ const [flow, setFlow] = react.useState(null);
543
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
544
+ const [error, setError] = react.useState(null);
545
+ const fetchFlow = react.useCallback(async () => {
546
+ if (options.skip || !options.flowSlug) return;
547
+ setIsLoading(true);
548
+ setError(null);
549
+ try {
550
+ const response = await client.getHelpFlow(options.flowSlug);
551
+ if (response.success && response.data) {
552
+ setFlow(response.data);
553
+ } else {
554
+ setError(getErrorMessage(response.error, "Failed to fetch flow"));
555
+ }
556
+ } catch (err) {
557
+ setError(getErrorMessage(err, "An error occurred"));
558
+ } finally {
559
+ setIsLoading(false);
560
+ }
561
+ }, [client, options.skip, options.flowSlug]);
562
+ react.useEffect(() => {
563
+ fetchFlow();
564
+ }, [fetchFlow]);
565
+ return {
566
+ flow,
567
+ isLoading,
568
+ error,
569
+ refetch: fetchFlow
570
+ };
571
+ }
572
+ function useHelpArticle(options) {
573
+ const { client } = useAppgramContext();
574
+ const [article, setArticle] = react.useState(null);
575
+ const [isLoading, setIsLoading] = react.useState(!options.skip);
576
+ const [error, setError] = react.useState(null);
577
+ const fetchArticle = react.useCallback(async () => {
578
+ if (options.skip || !options.articleSlug || !options.flowId) return;
579
+ setIsLoading(true);
580
+ setError(null);
581
+ try {
582
+ const response = await client.getHelpArticle(options.articleSlug, options.flowId);
583
+ if (response.success && response.data) {
584
+ setArticle(response.data);
585
+ } else {
586
+ setError(getErrorMessage(response.error, "Failed to fetch article"));
587
+ }
588
+ } catch (err) {
589
+ setError(getErrorMessage(err, "An error occurred"));
590
+ } finally {
591
+ setIsLoading(false);
592
+ }
593
+ }, [client, options.skip, options.articleSlug, options.flowId]);
594
+ react.useEffect(() => {
595
+ fetchArticle();
596
+ }, [fetchArticle]);
597
+ return {
598
+ article,
599
+ isLoading,
600
+ error,
601
+ refetch: fetchArticle
602
+ };
603
+ }
604
+ function useSupport(options = {}) {
605
+ const { client } = useAppgramContext();
606
+ const [isSubmitting, setIsSubmitting] = react.useState(false);
607
+ const [isSendingMagicLink, setIsSendingMagicLink] = react.useState(false);
608
+ const [isVerifying, setIsVerifying] = react.useState(false);
609
+ const [error, setError] = react.useState(null);
610
+ const [successMessage, setSuccessMessage] = react.useState(null);
611
+ const clearMessages = react.useCallback(() => {
612
+ setError(null);
613
+ setSuccessMessage(null);
614
+ }, []);
615
+ const submitTicket = react.useCallback(
616
+ async (data) => {
617
+ setIsSubmitting(true);
618
+ setError(null);
619
+ setSuccessMessage(null);
620
+ try {
621
+ const response = await client.submitSupportRequest(data);
622
+ if (response.success && response.data) {
623
+ setSuccessMessage("Your support request has been submitted successfully.");
624
+ options.onSubmitSuccess?.(response.data);
625
+ return response.data;
626
+ } else {
627
+ const errorMsg = getErrorMessage(response.error, "Failed to submit support request");
628
+ setError(errorMsg);
629
+ options.onSubmitError?.(errorMsg);
630
+ return null;
631
+ }
632
+ } catch (err) {
633
+ const errorMsg = getErrorMessage(err, "An error occurred");
634
+ setError(errorMsg);
635
+ options.onSubmitError?.(errorMsg);
636
+ return null;
637
+ } finally {
638
+ setIsSubmitting(false);
639
+ }
640
+ },
641
+ [client, options]
642
+ );
643
+ const requestMagicLink = react.useCallback(
644
+ async (email) => {
645
+ setIsSendingMagicLink(true);
646
+ setError(null);
647
+ setSuccessMessage(null);
648
+ try {
649
+ const response = await client.sendSupportMagicLink(email);
650
+ if (response.success) {
651
+ setSuccessMessage("A magic link has been sent to your email.");
652
+ return true;
653
+ } else {
654
+ setError(getErrorMessage(response.error, "Failed to send magic link"));
655
+ return false;
656
+ }
657
+ } catch (err) {
658
+ setError(getErrorMessage(err, "An error occurred"));
659
+ return false;
660
+ } finally {
661
+ setIsSendingMagicLink(false);
662
+ }
663
+ },
664
+ [client]
665
+ );
666
+ const verifyToken = react.useCallback(
667
+ async (token) => {
668
+ setIsVerifying(true);
669
+ setError(null);
670
+ try {
671
+ const response = await client.verifySupportToken(token);
672
+ if (response.success && response.data) {
673
+ return {
674
+ tickets: response.data.tickets,
675
+ userEmail: response.data.user_email
676
+ };
677
+ } else {
678
+ setError(getErrorMessage(response.error, "Invalid or expired token"));
679
+ return null;
680
+ }
681
+ } catch (err) {
682
+ setError(getErrorMessage(err, "An error occurred"));
683
+ return null;
684
+ } finally {
685
+ setIsVerifying(false);
686
+ }
687
+ },
688
+ [client]
689
+ );
690
+ const getTicket = react.useCallback(
691
+ async (ticketId, token) => {
692
+ setError(null);
693
+ try {
694
+ const response = await client.getSupportTicket(ticketId, token);
695
+ if (response.success && response.data) {
696
+ return response.data;
697
+ } else {
698
+ setError(getErrorMessage(response.error, "Failed to fetch ticket"));
699
+ return null;
700
+ }
701
+ } catch (err) {
702
+ setError(getErrorMessage(err, "An error occurred"));
703
+ return null;
704
+ }
705
+ },
706
+ [client]
707
+ );
708
+ const addMessage = react.useCallback(
709
+ async (ticketId, token, content) => {
710
+ setError(null);
711
+ try {
712
+ const response = await client.addSupportMessage(ticketId, token, content);
713
+ if (response.success && response.data) {
714
+ return response.data;
715
+ } else {
716
+ setError(getErrorMessage(response.error, "Failed to add message"));
717
+ return null;
718
+ }
719
+ } catch (err) {
720
+ setError(getErrorMessage(err, "An error occurred"));
721
+ return null;
722
+ }
723
+ },
724
+ [client]
725
+ );
726
+ return {
727
+ isSubmitting,
728
+ isSendingMagicLink,
729
+ isVerifying,
730
+ error,
731
+ successMessage,
732
+ submitTicket,
733
+ requestMagicLink,
734
+ verifyToken,
735
+ getTicket,
736
+ addMessage,
737
+ clearMessages
738
+ };
739
+ }
740
+
741
+ exports.AppgramContext = AppgramContext;
742
+ exports.cn = cn;
743
+ exports.getErrorMessage = getErrorMessage;
744
+ exports.getFingerprint = getFingerprint;
745
+ exports.resetFingerprint = resetFingerprint;
746
+ exports.useAppgramContext = useAppgramContext;
747
+ exports.useComments = useComments;
748
+ exports.useHelpArticle = useHelpArticle;
749
+ exports.useHelpCenter = useHelpCenter;
750
+ exports.useHelpFlow = useHelpFlow;
751
+ exports.useRelease = useRelease;
752
+ exports.useReleases = useReleases;
753
+ exports.useRoadmap = useRoadmap;
754
+ exports.useSupport = useSupport;
755
+ exports.useVote = useVote;
756
+ exports.useWishes = useWishes;
757
+ //# sourceMappingURL=chunk-75P634IK.js.map
758
+ //# sourceMappingURL=chunk-75P634IK.js.map