@tagadapay/plugin-sdk 2.6.18 → 2.7.2

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 (40) hide show
  1. package/dist/react/hooks/usePluginConfig.js +15 -7
  2. package/dist/v2/core/index.d.ts +1 -0
  3. package/dist/v2/core/index.js +2 -0
  4. package/dist/v2/core/pathRemapping.d.ts +156 -0
  5. package/dist/v2/core/pathRemapping.js +440 -0
  6. package/dist/v2/core/resources/credits.d.ts +42 -0
  7. package/dist/v2/core/resources/credits.js +21 -0
  8. package/dist/v2/core/resources/customer.d.ts +150 -0
  9. package/dist/v2/core/resources/customer.js +53 -0
  10. package/dist/v2/core/resources/index.d.ts +4 -1
  11. package/dist/v2/core/resources/index.js +4 -1
  12. package/dist/v2/core/resources/session.d.ts +27 -0
  13. package/dist/v2/core/resources/session.js +56 -0
  14. package/dist/v2/core/utils/pluginConfig.d.ts +14 -0
  15. package/dist/v2/core/utils/pluginConfig.js +96 -29
  16. package/dist/v2/index.d.ts +11 -2
  17. package/dist/v2/index.js +3 -1
  18. package/dist/v2/react/hooks/useAuth.d.ts +8 -0
  19. package/dist/v2/react/hooks/useAuth.js +9 -0
  20. package/dist/v2/react/hooks/useClubOffers.d.ts +101 -0
  21. package/dist/v2/react/hooks/useClubOffers.js +126 -0
  22. package/dist/v2/react/hooks/useCredits.d.ts +67 -0
  23. package/dist/v2/react/hooks/useCredits.js +80 -0
  24. package/dist/v2/react/hooks/useCustomer.d.ts +11 -0
  25. package/dist/v2/react/hooks/useCustomer.js +11 -0
  26. package/dist/v2/react/hooks/useCustomerInfos.d.ts +12 -0
  27. package/dist/v2/react/hooks/useCustomerInfos.js +53 -0
  28. package/dist/v2/react/hooks/useCustomerOrders.d.ts +17 -0
  29. package/dist/v2/react/hooks/useCustomerOrders.js +51 -0
  30. package/dist/v2/react/hooks/useCustomerSubscriptions.d.ts +23 -0
  31. package/dist/v2/react/hooks/useCustomerSubscriptions.js +94 -0
  32. package/dist/v2/react/hooks/useLogin.d.ts +53 -0
  33. package/dist/v2/react/hooks/useLogin.js +75 -0
  34. package/dist/v2/react/hooks/useTranslation.d.ts +40 -3
  35. package/dist/v2/react/hooks/useTranslation.js +128 -16
  36. package/dist/v2/react/index.d.ts +18 -1
  37. package/dist/v2/react/index.js +9 -0
  38. package/package.json +2 -1
  39. package/dist/v2/react/hooks/useDiscountQuery.d.ts +0 -79
  40. package/dist/v2/react/hooks/useDiscountQuery.js +0 -24
@@ -0,0 +1,101 @@
1
+ export interface ClubOfferItem {
2
+ id: string;
3
+ productId: string;
4
+ variantId: string;
5
+ product: {
6
+ name: string;
7
+ description: string;
8
+ };
9
+ variant: {
10
+ name: string;
11
+ description: string;
12
+ imageUrl: string;
13
+ grams: number;
14
+ };
15
+ unitAmount: number;
16
+ quantity: number;
17
+ amount: number;
18
+ adjustedAmount: number;
19
+ }
20
+ export interface ClubOfferSummary {
21
+ currency: string;
22
+ totalAmount: number;
23
+ totalAdjustedAmount: number;
24
+ items: ClubOfferItem[];
25
+ }
26
+ export interface ClubOfferLineItem {
27
+ id: string;
28
+ quantity: number;
29
+ price: {
30
+ variant: {
31
+ id: string;
32
+ name: string;
33
+ description: string | null;
34
+ imageUrl: string;
35
+ grams: number;
36
+ product: {
37
+ id: string;
38
+ name: string;
39
+ description: string;
40
+ };
41
+ };
42
+ };
43
+ }
44
+ export interface ClubOffer {
45
+ id: string;
46
+ titleTrans: {
47
+ en: string;
48
+ };
49
+ summaries: ClubOfferSummary[];
50
+ offerLineItems: ClubOfferLineItem[];
51
+ }
52
+ export interface UseClubOffersOptions {
53
+ /**
54
+ * Whether to fetch club offers automatically on mount
55
+ * @default true
56
+ */
57
+ enabled?: boolean;
58
+ /**
59
+ * Return URL for payment
60
+ */
61
+ returnUrl?: string;
62
+ }
63
+ export interface UseClubOffersResult {
64
+ /**
65
+ * Array of fetched club offers
66
+ */
67
+ offers: ClubOffer[];
68
+ /**
69
+ * Loading state
70
+ */
71
+ isLoading: boolean;
72
+ /**
73
+ * Error state
74
+ */
75
+ error: Error | null;
76
+ /**
77
+ * Refetch club offers
78
+ */
79
+ refetch: () => Promise<void>;
80
+ /**
81
+ * Get club offer by ID from the loaded offers
82
+ */
83
+ getOffer: (offerId: string) => ClubOffer | undefined;
84
+ /**
85
+ * Get total value of all club offers
86
+ */
87
+ getTotalValue: () => number;
88
+ /**
89
+ * Get total savings across all club offers
90
+ */
91
+ getTotalSavings: () => number;
92
+ /**
93
+ * Clear error state
94
+ */
95
+ clearError: () => void;
96
+ /**
97
+ * Pay for a club offer
98
+ */
99
+ payOffer: (offerId: string, returnUrl?: string) => Promise<void>;
100
+ }
101
+ export declare function useClubOffers(options?: UseClubOffersOptions): UseClubOffersResult;
@@ -0,0 +1,126 @@
1
+ 'use client';
2
+ /**
3
+ * useClubOffers - Hook for club-specific offers (v2)
4
+ * Extends the offers functionality with club filtering
5
+ */
6
+ import { useMutation, useQuery } from '@tanstack/react-query';
7
+ import { useCallback, useMemo } from 'react';
8
+ import { OffersResource } from '../../core/resources/offers';
9
+ import { useTagadaContext } from '../providers/TagadaProvider';
10
+ import { getGlobalApiClient } from './useApiQuery';
11
+ import { usePluginConfig } from './usePluginConfig';
12
+ /**
13
+ * Transform generic Offer to ClubOffer format
14
+ */
15
+ function transformToClubOffer(offer) {
16
+ return {
17
+ id: offer.id,
18
+ titleTrans: offer.titleTrans,
19
+ summaries: offer.summaries.map((summary) => ({
20
+ currency: summary.currency,
21
+ totalAmount: summary.totalAmount,
22
+ totalAdjustedAmount: summary.totalAdjustedAmount,
23
+ items: summary.items.map((item) => ({
24
+ id: item.id,
25
+ productId: item.id, // Using item ID as productId fallback
26
+ variantId: item.id, // Using item ID as variantId fallback
27
+ product: item.product,
28
+ variant: {
29
+ name: item.variant.name,
30
+ description: '', // Not available in base Offer
31
+ imageUrl: item.variant.imageUrl,
32
+ grams: 0, // Not available in base Offer
33
+ },
34
+ unitAmount: item.unitAmount,
35
+ quantity: item.quantity,
36
+ amount: item.amount,
37
+ adjustedAmount: item.adjustedAmount,
38
+ })),
39
+ })),
40
+ offerLineItems: [], // Not available in base Offer
41
+ };
42
+ }
43
+ export function useClubOffers(options = {}) {
44
+ const { enabled = true, returnUrl } = options;
45
+ const { storeId } = usePluginConfig();
46
+ const { isSessionInitialized } = useTagadaContext();
47
+ // Create offers resource client
48
+ const offersResource = useMemo(() => {
49
+ try {
50
+ return new OffersResource(getGlobalApiClient());
51
+ }
52
+ catch (error) {
53
+ throw new Error('Failed to initialize offers resource: ' +
54
+ (error instanceof Error ? error.message : 'Unknown error'));
55
+ }
56
+ }, []);
57
+ // Create query key
58
+ const queryKey = useMemo(() => ['club-offers', { storeId }], [storeId]);
59
+ // Fetch club offers using TanStack Query
60
+ const { data: offers = [], isLoading, error, refetch, } = useQuery({
61
+ queryKey,
62
+ enabled: enabled && !!storeId && isSessionInitialized,
63
+ queryFn: async () => {
64
+ if (!storeId) {
65
+ throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
66
+ }
67
+ // Fetch all offers and filter for club type
68
+ // Note: The API endpoint should support a 'type' parameter
69
+ const response = await getGlobalApiClient().get(`/api/v1/stores/${storeId}/offers`, {
70
+ params: {
71
+ type: 'club',
72
+ },
73
+ });
74
+ // Transform to club offer format
75
+ return (response.offers || []).map(transformToClubOffer);
76
+ },
77
+ staleTime: 5 * 60 * 1000, // 5 minutes
78
+ refetchOnWindowFocus: false,
79
+ });
80
+ // Pay offer mutation
81
+ const payOfferMutation = useMutation({
82
+ mutationFn: async ({ offerId, returnUrl }) => {
83
+ const url = returnUrl || (typeof window !== 'undefined' ? window.location.href : '');
84
+ return await offersResource.payOffer(offerId);
85
+ },
86
+ onError: (error) => {
87
+ console.error('[SDK] Failed to pay offer:', error);
88
+ },
89
+ });
90
+ // Helper functions
91
+ const getOffer = useCallback((offerId) => {
92
+ return offers.find((offer) => offer.id === offerId);
93
+ }, [offers]);
94
+ const getTotalValue = useCallback(() => {
95
+ return offers.reduce((total, offer) => {
96
+ const firstSummary = offer.summaries[0];
97
+ return total + (firstSummary?.totalAdjustedAmount || 0);
98
+ }, 0);
99
+ }, [offers]);
100
+ const getTotalSavings = useCallback(() => {
101
+ return offers.reduce((total, offer) => {
102
+ const firstSummary = offer.summaries[0];
103
+ return total + (firstSummary?.totalAmount - firstSummary?.totalAdjustedAmount || 0);
104
+ }, 0);
105
+ }, [offers]);
106
+ const clearError = useCallback(() => {
107
+ // TanStack Query doesn't have a direct clearError method
108
+ // Error will be cleared on next successful fetch
109
+ }, []);
110
+ const payOffer = useCallback(async (offerId, returnUrl) => {
111
+ await payOfferMutation.mutateAsync({ offerId, returnUrl });
112
+ }, [payOfferMutation]);
113
+ return {
114
+ offers,
115
+ isLoading,
116
+ error,
117
+ refetch: async () => {
118
+ await refetch();
119
+ },
120
+ getOffer,
121
+ getTotalValue,
122
+ getTotalSavings,
123
+ clearError,
124
+ payOffer,
125
+ };
126
+ }
@@ -0,0 +1,67 @@
1
+ import { CreditTransaction, RedeemProductResponse } from '../../core/resources/credits';
2
+ export interface UseCreditsOptions {
3
+ /**
4
+ * Customer ID to fetch credits for
5
+ */
6
+ customerId?: string | null;
7
+ /**
8
+ * Whether to fetch credits automatically on mount
9
+ * @default true
10
+ */
11
+ enabled?: boolean;
12
+ }
13
+ export interface UseCreditsResult {
14
+ /**
15
+ * Customer credit balance
16
+ */
17
+ balance: number;
18
+ /**
19
+ * Lifetime credits earned
20
+ */
21
+ lifetimeEarned: number;
22
+ /**
23
+ * Lifetime credits spent
24
+ */
25
+ lifetimeSpent: number;
26
+ /**
27
+ * Credit transaction history
28
+ */
29
+ transactions: CreditTransaction[];
30
+ /**
31
+ * Loading state
32
+ */
33
+ isLoading: boolean;
34
+ /**
35
+ * Error state
36
+ */
37
+ error: Error | null;
38
+ /**
39
+ * Refetch credit balance and history
40
+ */
41
+ refetch: () => Promise<void>;
42
+ /**
43
+ * Redeem a product using credits
44
+ */
45
+ redeemProduct: (data: {
46
+ productId?: string;
47
+ variantId: string;
48
+ quantity?: number;
49
+ }) => Promise<RedeemProductResponse>;
50
+ /**
51
+ * Check if customer has enough credits for a purchase
52
+ */
53
+ hasEnoughCredits: (amount: number) => boolean;
54
+ /**
55
+ * Get transaction by ID
56
+ */
57
+ getTransaction: (transactionId: string) => CreditTransaction | undefined;
58
+ /**
59
+ * Redemption mutation state
60
+ */
61
+ isRedeeming: boolean;
62
+ /**
63
+ * Redemption error state
64
+ */
65
+ redeemError: Error | null;
66
+ }
67
+ export declare function useCredits(options?: UseCreditsOptions): UseCreditsResult;
@@ -0,0 +1,80 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2
+ import { useCallback, useMemo } from 'react';
3
+ import { CreditsResource } from '../../core/resources/credits';
4
+ import { useTagadaContext } from '../providers/TagadaProvider';
5
+ import { getGlobalApiClient } from './useApiQuery';
6
+ import { usePluginConfig } from './usePluginConfig';
7
+ export function useCredits(options = {}) {
8
+ const { customerId = null, enabled = true } = options;
9
+ const { storeId } = usePluginConfig();
10
+ const { isSessionInitialized } = useTagadaContext();
11
+ const queryClient = useQueryClient();
12
+ // Create credits resource client
13
+ const creditsResource = useMemo(() => {
14
+ try {
15
+ return new CreditsResource(getGlobalApiClient());
16
+ }
17
+ catch (error) {
18
+ throw new Error('Failed to initialize credits resource: ' +
19
+ (error instanceof Error ? error.message : 'Unknown error'));
20
+ }
21
+ }, []);
22
+ // Determine if query should be enabled
23
+ const isEnabled = useMemo(() => {
24
+ return Boolean(enabled && customerId && storeId && isSessionInitialized);
25
+ }, [enabled, customerId, storeId, isSessionInitialized]);
26
+ // Create query key
27
+ const queryKey = useMemo(() => ['customer-credits', { customerId, storeId }], [customerId, storeId]);
28
+ // Fetch customer credits using TanStack Query
29
+ const { data = null, isLoading, error, refetch, } = useQuery({
30
+ queryKey,
31
+ enabled: isEnabled,
32
+ queryFn: async () => {
33
+ if (!customerId || !storeId) {
34
+ return null;
35
+ }
36
+ return await creditsResource.getCustomerCredits(customerId, storeId);
37
+ },
38
+ staleTime: 30 * 1000, // 30 seconds - fresher than most resources
39
+ refetchOnWindowFocus: true, // Refetch on window focus for up-to-date balance
40
+ });
41
+ // Redeem product mutation
42
+ const redeemMutation = useMutation({
43
+ mutationFn: async (redeemData) => {
44
+ return await creditsResource.redeemProduct(redeemData);
45
+ },
46
+ onSuccess: () => {
47
+ // Invalidate credits query to refetch updated balance
48
+ void queryClient.invalidateQueries({ queryKey });
49
+ },
50
+ onError: (error) => {
51
+ console.error('[SDK] Failed to redeem product with credits:', error);
52
+ },
53
+ });
54
+ // Helper functions
55
+ const hasEnoughCredits = useCallback((amount) => {
56
+ return (data?.balance ?? 0) >= amount;
57
+ }, [data?.balance]);
58
+ const getTransaction = useCallback((transactionId) => {
59
+ return data?.transactions.find((tx) => tx.id === transactionId);
60
+ }, [data?.transactions]);
61
+ const redeemProduct = useCallback(async (redeemData) => {
62
+ return await redeemMutation.mutateAsync(redeemData);
63
+ }, [redeemMutation]);
64
+ return {
65
+ balance: data?.balance ?? 0,
66
+ lifetimeEarned: data?.lifetimeEarned ?? 0,
67
+ lifetimeSpent: data?.lifetimeSpent ?? 0,
68
+ transactions: data?.transactions ?? [],
69
+ isLoading,
70
+ error,
71
+ refetch: async () => {
72
+ await refetch();
73
+ },
74
+ redeemProduct,
75
+ hasEnoughCredits,
76
+ getTransaction,
77
+ isRedeeming: redeemMutation.isPending,
78
+ redeemError: redeemMutation.error,
79
+ };
80
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * useCustomer - Hook to access current customer data (v2)
3
+ */
4
+ import { Customer } from '../../../react/types';
5
+ export interface UseCustomerResult {
6
+ customer: Customer | null;
7
+ isAuthenticated: boolean;
8
+ isLoading: boolean;
9
+ isAnonymous: boolean;
10
+ }
11
+ export declare function useCustomer(): UseCustomerResult;
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import { useTagadaContext } from '../providers/TagadaProvider';
3
+ export function useCustomer() {
4
+ const { customer, isLoading } = useTagadaContext();
5
+ return {
6
+ customer,
7
+ isAuthenticated: customer?.isAuthenticated || false,
8
+ isLoading,
9
+ isAnonymous: customer?.role === 'anonymous',
10
+ };
11
+ }
@@ -0,0 +1,12 @@
1
+ import { CustomerInfos } from '../../core/resources/customer';
2
+ export interface UseCustomerInfosOptions {
3
+ customerId?: string | null;
4
+ enabled?: boolean;
5
+ }
6
+ export interface UseCustomerInfosResult {
7
+ data: CustomerInfos | null;
8
+ isLoading: boolean;
9
+ error: Error | null;
10
+ refetch: () => Promise<void>;
11
+ }
12
+ export declare function useCustomerInfos(options?: UseCustomerInfosOptions): UseCustomerInfosResult;
@@ -0,0 +1,53 @@
1
+ 'use client';
2
+ /**
3
+ * useCustomerInfos - Hook to fetch customer information (v2)
4
+ * Fetches customer infos from `/api/v1/customers/{customerId}` with `storeId` param
5
+ */
6
+ import { useQuery } from '@tanstack/react-query';
7
+ import { useMemo } from 'react';
8
+ import { CustomerResource } from '../../core/resources/customer';
9
+ import { useTagadaContext } from '../providers/TagadaProvider';
10
+ import { getGlobalApiClient } from './useApiQuery';
11
+ import { usePluginConfig } from './usePluginConfig';
12
+ export function useCustomerInfos(options = {}) {
13
+ const { storeId } = usePluginConfig();
14
+ const { isSessionInitialized } = useTagadaContext();
15
+ const { customerId = null, enabled = true } = options;
16
+ // Create customer resource client
17
+ const customerResource = useMemo(() => {
18
+ try {
19
+ return new CustomerResource(getGlobalApiClient());
20
+ }
21
+ catch (error) {
22
+ throw new Error('Failed to initialize customer resource: ' +
23
+ (error instanceof Error ? error.message : 'Unknown error'));
24
+ }
25
+ }, []);
26
+ // Determine if query should be enabled
27
+ const isEnabled = useMemo(() => {
28
+ return Boolean(enabled && customerId && storeId && isSessionInitialized);
29
+ }, [enabled, customerId, storeId, isSessionInitialized]);
30
+ // Create query key
31
+ const queryKey = useMemo(() => ['customer-infos', { customerId, storeId }], [customerId, storeId]);
32
+ // Fetch customer infos using TanStack Query
33
+ const { data = null, isLoading, error, refetch, } = useQuery({
34
+ queryKey,
35
+ enabled: isEnabled,
36
+ queryFn: async () => {
37
+ if (!customerId || !storeId) {
38
+ return null;
39
+ }
40
+ return await customerResource.getCustomerInfos(customerId, storeId);
41
+ },
42
+ staleTime: 5 * 60 * 1000, // 5 minutes
43
+ refetchOnWindowFocus: false,
44
+ });
45
+ return {
46
+ data,
47
+ isLoading,
48
+ error,
49
+ refetch: async () => {
50
+ await refetch();
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * useCustomerOrders - Hook to fetch customer orders (v2)
3
+ */
4
+ import { OrderWithRelations } from '../../core/resources/customer';
5
+ export interface UseCustomerOrdersOptions {
6
+ customerId?: string | null;
7
+ enabled?: boolean;
8
+ }
9
+ export interface UseCustomerOrdersResult {
10
+ data: {
11
+ orders: OrderWithRelations[];
12
+ } | null;
13
+ isLoading: boolean;
14
+ error: Error | null;
15
+ refetch: () => Promise<void>;
16
+ }
17
+ export declare function useCustomerOrders(options?: UseCustomerOrdersOptions): UseCustomerOrdersResult;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * useCustomerOrders - Hook to fetch customer orders (v2)
3
+ */
4
+ import { useQuery } from '@tanstack/react-query';
5
+ import { useMemo } from 'react';
6
+ import { CustomerResource } from '../../core/resources/customer';
7
+ import { useTagadaContext } from '../providers/TagadaProvider';
8
+ import { getGlobalApiClient } from './useApiQuery';
9
+ import { usePluginConfig } from './usePluginConfig';
10
+ export function useCustomerOrders(options = {}) {
11
+ const { storeId } = usePluginConfig();
12
+ const { isSessionInitialized } = useTagadaContext();
13
+ const { customerId = null, enabled = true } = options;
14
+ // Create customer resource client
15
+ const customerResource = useMemo(() => {
16
+ try {
17
+ return new CustomerResource(getGlobalApiClient());
18
+ }
19
+ catch (error) {
20
+ throw new Error('Failed to initialize customer resource: ' +
21
+ (error instanceof Error ? error.message : 'Unknown error'));
22
+ }
23
+ }, []);
24
+ // Determine if query should be enabled
25
+ const isEnabled = useMemo(() => {
26
+ return Boolean(enabled && customerId && storeId && isSessionInitialized);
27
+ }, [enabled, customerId, storeId, isSessionInitialized]);
28
+ // Create query key
29
+ const queryKey = useMemo(() => ['customer-orders', { customerId, storeId }], [customerId, storeId]);
30
+ // Fetch customer orders using TanStack Query
31
+ const { data = null, isLoading, error, refetch, } = useQuery({
32
+ queryKey,
33
+ enabled: isEnabled,
34
+ queryFn: async () => {
35
+ if (!customerId || !storeId) {
36
+ return null;
37
+ }
38
+ return await customerResource.getCustomerOrders(customerId, storeId);
39
+ },
40
+ staleTime: 5 * 60 * 1000, // 5 minutes
41
+ refetchOnWindowFocus: false,
42
+ });
43
+ return {
44
+ data,
45
+ isLoading,
46
+ error,
47
+ refetch: async () => {
48
+ await refetch();
49
+ },
50
+ };
51
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * useCustomerSubscriptions - Hook to manage customer subscriptions (v2)
3
+ */
4
+ import { SubscriptionsResponse } from '../../core/resources/customer';
5
+ export interface UseCustomerSubscriptionsOptions {
6
+ customerId?: string | null;
7
+ enabled?: boolean;
8
+ }
9
+ export interface UseCustomerSubscriptionsResult {
10
+ data: SubscriptionsResponse | null;
11
+ isLoading: boolean;
12
+ error: Error | null;
13
+ refetch: () => Promise<void>;
14
+ resumeSubscription: (subscriptionId: string) => Promise<{
15
+ success: boolean;
16
+ error?: string;
17
+ }>;
18
+ cancelSubscription: (subscriptionId: string) => Promise<{
19
+ success: boolean;
20
+ error?: string;
21
+ }>;
22
+ }
23
+ export declare function useCustomerSubscriptions(options?: UseCustomerSubscriptionsOptions): UseCustomerSubscriptionsResult;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * useCustomerSubscriptions - Hook to manage customer subscriptions (v2)
3
+ */
4
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
5
+ import { useCallback, useMemo } from 'react';
6
+ import { CustomerResource } from '../../core/resources/customer';
7
+ import { useTagadaContext } from '../providers/TagadaProvider';
8
+ import { getGlobalApiClient } from './useApiQuery';
9
+ export function useCustomerSubscriptions(options = {}) {
10
+ const { isSessionInitialized } = useTagadaContext();
11
+ const queryClient = useQueryClient();
12
+ const { customerId = null, enabled = true } = options;
13
+ // Create customer resource client
14
+ const customerResource = useMemo(() => {
15
+ try {
16
+ return new CustomerResource(getGlobalApiClient());
17
+ }
18
+ catch (error) {
19
+ throw new Error('Failed to initialize customer resource: ' +
20
+ (error instanceof Error ? error.message : 'Unknown error'));
21
+ }
22
+ }, []);
23
+ // Determine if query should be enabled
24
+ const isEnabled = useMemo(() => {
25
+ return Boolean(enabled && customerId && isSessionInitialized);
26
+ }, [enabled, customerId, isSessionInitialized]);
27
+ // Create query key
28
+ const queryKey = useMemo(() => ['customer-subscriptions', { customerId }], [customerId]);
29
+ // Fetch customer subscriptions using TanStack Query
30
+ const { data = null, isLoading, error, refetch, } = useQuery({
31
+ queryKey,
32
+ enabled: isEnabled,
33
+ queryFn: async () => {
34
+ if (!customerId) {
35
+ return null;
36
+ }
37
+ return await customerResource.getCustomerSubscriptions();
38
+ },
39
+ staleTime: 5 * 60 * 1000, // 5 minutes
40
+ refetchOnWindowFocus: false,
41
+ });
42
+ // Resume subscription mutation
43
+ const resumeMutation = useMutation({
44
+ mutationFn: async (subscriptionId) => {
45
+ return await customerResource.resumeSubscription(subscriptionId);
46
+ },
47
+ onSuccess: () => {
48
+ // Invalidate and refetch subscriptions
49
+ void queryClient.invalidateQueries({ queryKey });
50
+ },
51
+ });
52
+ // Cancel subscription mutation
53
+ const cancelMutation = useMutation({
54
+ mutationFn: async (subscriptionId) => {
55
+ return await customerResource.cancelSubscription(subscriptionId);
56
+ },
57
+ onSuccess: () => {
58
+ // Invalidate and refetch subscriptions
59
+ void queryClient.invalidateQueries({ queryKey });
60
+ },
61
+ });
62
+ // Resume subscription
63
+ const resumeSubscription = useCallback(async (subscriptionId) => {
64
+ try {
65
+ await resumeMutation.mutateAsync(subscriptionId);
66
+ return { success: true };
67
+ }
68
+ catch (err) {
69
+ const errorMessage = err instanceof Error ? err.message : 'Failed to resume subscription';
70
+ return { success: false, error: errorMessage };
71
+ }
72
+ }, [resumeMutation]);
73
+ // Cancel subscription
74
+ const cancelSubscription = useCallback(async (subscriptionId) => {
75
+ try {
76
+ await cancelMutation.mutateAsync(subscriptionId);
77
+ return { success: true };
78
+ }
79
+ catch (err) {
80
+ const errorMessage = err instanceof Error ? err.message : 'Failed to cancel subscription';
81
+ return { success: false, error: errorMessage };
82
+ }
83
+ }, [cancelMutation]);
84
+ return {
85
+ data,
86
+ isLoading,
87
+ error,
88
+ refetch: async () => {
89
+ await refetch();
90
+ },
91
+ resumeSubscription,
92
+ cancelSubscription,
93
+ };
94
+ }