@umituz/react-native-subscription 2.37.13 → 2.37.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domains/credits/application/PurchaseMetadataGenerator.ts +1 -1
- package/src/domains/credits/application/credit-strategies/CreditAllocationOrchestrator.ts +1 -1
- package/src/domains/credits/application/creditDocumentHelpers.ts +0 -14
- package/src/domains/credits/presentation/deduct-credit/index.ts +0 -1
- package/src/domains/credits/presentation/useCredits.ts +1 -6
- package/src/domains/credits/utils/creditValidation.ts +3 -3
- package/src/domains/paywall/components/PaywallFeatures.tsx +1 -1
- package/src/domains/paywall/hooks/usePaywallActions.ts +1 -1
- package/src/domains/revenuecat/core/errors/RevenueCatError.ts +1 -14
- package/src/domains/revenuecat/core/errors/RevenueCatErrorHandler.ts +1 -1
- package/src/domains/revenuecat/core/types/RevenueCatTypes.ts +3 -3
- package/src/domains/revenuecat/infrastructure/services/ConfigurationStateManager.ts +8 -2
- package/src/domains/revenuecat/infrastructure/services/RevenueCatInitializer.ts +0 -2
- package/src/domains/subscription/application/initializer/BackgroundInitializer.ts +45 -16
- package/src/domains/subscription/application/initializer/index.ts +1 -1
- package/src/domains/subscription/core/SubscriptionStatus.ts +4 -10
- package/src/domains/subscription/core/SubscriptionStatusHandlers.ts +1 -1
- package/src/domains/subscription/infrastructure/handlers/PackageHandler.ts +0 -2
- package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +1 -1
- package/src/domains/subscription/infrastructure/hooks/useRevenueCatTrialEligibility.ts +1 -2
- package/src/domains/subscription/infrastructure/hooks/useSubscriptionQueries.ts +0 -4
- package/src/domains/subscription/infrastructure/services/OfferingsFetcher.ts +50 -22
- package/src/domains/subscription/infrastructure/services/RestoreHandler.ts +1 -1
- package/src/domains/subscription/infrastructure/services/RevenueCatService.ts +1 -2
- package/src/domains/subscription/infrastructure/services/revenueCatServiceInstance.ts +0 -4
- package/src/domains/subscription/infrastructure/utils/renewal/index.ts +1 -1
- package/src/domains/subscription/presentation/components/details/CreditRow.tsx +1 -1
- package/src/domains/subscription/presentation/components/details/DetailRow.tsx +1 -1
- package/src/domains/subscription/presentation/components/feedback/FeedbackOption.tsx +0 -2
- package/src/domains/subscription/presentation/components/feedback/FeedbackTextInput.tsx +1 -1
- package/src/domains/subscription/presentation/featureGateRefs.ts +1 -1
- package/src/domains/subscription/presentation/screens/components/CreditsList.tsx +2 -2
- package/src/domains/subscription/presentation/screens/components/SubscriptionHeader.tsx +0 -2
- package/src/domains/subscription/presentation/stores/index.ts +0 -5
- package/src/domains/subscription/presentation/stores/purchaseLoadingStore.ts +3 -7
- package/src/domains/subscription/presentation/useAuthAwarePurchase.ts +2 -8
- package/src/domains/subscription/presentation/useFeatureGate.ts +0 -2
- package/src/domains/subscription/presentation/usePaywallVisibility.ts +1 -1
- package/src/domains/subscription/utils/authGuards.ts +0 -23
- package/src/domains/subscription/utils/syncStatus.ts +1 -1
- package/src/domains/wallet/index.ts +0 -112
- package/src/domains/wallet/infrastructure/config/walletConfig.ts +1 -23
- package/src/domains/wallet/infrastructure/repositories/transaction/CollectionBuilder.ts +1 -1
- package/src/domains/wallet/infrastructure/repositories/transaction/index.ts +0 -9
- package/src/domains/wallet/presentation/components/BalanceCard.tsx +1 -1
- package/src/domains/wallet/presentation/components/TransactionItem.tsx +0 -2
- package/src/domains/wallet/presentation/components/TransactionList.tsx +3 -2
- package/src/domains/wallet/presentation/hooks/useTransactionHistory.ts +2 -2
- package/src/domains/wallet/presentation/hooks/useWallet.ts +2 -2
- package/src/shared/application/FeedbackService.ts +2 -2
- package/src/shared/infrastructure/SubscriptionEventBus.ts +1 -1
- package/src/shared/infrastructure/firestore/collectionUtils.ts +0 -7
- package/src/shared/infrastructure/firestore/resultUtils.ts +3 -39
- package/src/shared/presentation/layouts/ScreenLayout.tsx +1 -1
- package/src/shared/utils/numberUtils.core.ts +0 -27
- package/src/shared/utils/numberUtils.ts +1 -9
- package/src/shared/utils/validators.ts +0 -58
- package/src/domains/config/domain/entities/Plan.ts +0 -44
- package/src/domains/config/domain/index.ts +0 -2
- package/src/domains/config/domain/value-objects/Config.ts +0 -49
- package/src/domains/config/index.ts +0 -6
- package/src/domains/config/utils/planSelectors.ts +0 -56
- package/src/domains/paywall/components/FeatureItem.tsx +0 -50
- package/src/domains/paywall/components/FeatureList.tsx +0 -34
- package/src/domains/paywall/components/PaywallHeader.tsx +0 -112
- package/src/domains/paywall/hooks/usePaywallTranslations.ts +0 -78
- package/src/domains/paywall/hooks/useSubscriptionModal.ts +0 -45
- package/src/domains/paywall/index.ts +0 -13
- package/src/domains/revenuecat/core/constants/RevenueCatConstants.ts +0 -201
- package/src/domains/revenuecat/core/constants/index.ts +0 -5
- package/src/domains/revenuecat/core/customerInfoHelpers.ts +0 -21
- package/src/domains/revenuecat/core/index.ts +0 -7
- package/src/domains/revenuecat/index.ts +0 -7
- package/src/domains/revenuecat/infrastructure/index.ts +0 -5
- package/src/domains/revenuecat/infrastructure/services/index.ts +0 -7
- package/src/domains/subscription/infrastructure/hooks/customer-info/index.ts +0 -2
- package/src/domains/subscription/infrastructure/hooks/customer-info/types.ts +0 -9
- package/src/domains/subscription/infrastructure/hooks/customer-info/useCustomerInfo.ts +0 -52
- package/src/domains/subscription/infrastructure/hooks/useInitializeSubscription.ts +0 -30
- package/src/domains/subscription/infrastructure/hooks/usePaywallFlow.ts +0 -78
- package/src/domains/subscription/infrastructure/hooks/useRevenueCat.ts +0 -119
- package/src/domains/subscription/presentation/components/feedback/FeedbackConstants.ts +0 -6
- package/src/domains/subscription/presentation/screens/components/SubscriptionActions.tsx +0 -56
- package/src/domains/subscription/utils/dateFormatters.ts +0 -28
- package/src/domains/wallet/domain/entities/CreditCost.ts +0 -45
- package/src/domains/wallet/domain/entities/README.md +0 -41
- package/src/domains/wallet/domain/errors/README.md +0 -40
- package/src/domains/wallet/domain/errors/WalletError.ts +0 -17
- package/src/domains/wallet/domain/errors/WalletError.types.ts +0 -30
- package/src/domains/wallet/domain/errors/WalletErrorClasses.ts +0 -82
- package/src/domains/wallet/domain/errors/WalletErrorFactory.ts +0 -24
- package/src/domains/wallet/domain/errors/WalletErrorMessages.ts +0 -17
- package/src/domains/wallet/domain/types/credit-cost.types.ts +0 -86
- package/src/domains/wallet/domain/types/index.ts +0 -33
- package/src/domains/wallet/domain/types/wallet.types.ts +0 -50
- package/src/domains/wallet/infrastructure/services/product-metadata/CacheManager.ts +0 -30
- package/src/domains/wallet/infrastructure/services/product-metadata/FirebaseFetcher.ts +0 -17
- package/src/domains/wallet/infrastructure/services/product-metadata/ProductMetadataService.ts +0 -57
- package/src/domains/wallet/infrastructure/services/product-metadata/ServiceManager.ts +0 -29
- package/src/domains/wallet/infrastructure/services/product-metadata/index.ts +0 -7
- package/src/domains/wallet/presentation/hooks/index.ts +0 -8
- package/src/domains/wallet/presentation/hooks/useProductMetadata.ts +0 -72
- package/src/domains/wallet/utils/index.ts +0 -1
- package/src/shared/application/ActivationHandler.ts +0 -108
- package/src/shared/application/ports/ISubscriptionService.ts +0 -27
- package/src/shared/infrastructure/index.ts +0 -6
- package/src/shared/infrastructure/react-query/queryInvalidation.ts +0 -46
- package/src/shared/presentation/hooks/index.ts +0 -6
- package/src/shared/presentation/hooks/useAsyncState.ts +0 -72
- package/src/shared/presentation/hooks/useServiceCall.ts +0 -77
- package/src/shared/types/ReactTypes.ts +0 -80
- package/src/shared/utils/InsufficientCreditsError.ts +0 -32
- package/src/shared/utils/Logger.ts +0 -81
- package/src/shared/utils/SubscriptionConfig.ts +0 -15
- package/src/shared/utils/SubscriptionError.ts +0 -47
- package/src/shared/utils/appValidators.ts +0 -38
- package/src/shared/utils/arrayUtils.core.ts +0 -81
- package/src/shared/utils/arrayUtils.query.ts +0 -118
- package/src/shared/utils/arrayUtils.transforms.ts +0 -116
- package/src/shared/utils/arrayUtils.ts +0 -19
- package/src/shared/utils/errorUtils.ts +0 -32
- package/src/shared/utils/index.ts +0 -14
- package/src/shared/utils/numberUtils.aggregate.ts +0 -35
- package/src/shared/utils/numberUtils.format.ts +0 -42
- package/src/shared/utils/numberUtils.math.ts +0 -48
- package/src/shared/utils/queryKeyFactory.ts +0 -9
- package/src/shared/utils/stringUtils.case.ts +0 -64
- package/src/shared/utils/stringUtils.check.ts +0 -65
- package/src/shared/utils/stringUtils.format.ts +0 -84
- package/src/shared/utils/stringUtils.generate.ts +0 -47
- package/src/shared/utils/stringUtils.modify.ts +0 -67
- package/src/shared/utils/stringUtils.ts +0 -10
|
@@ -9,16 +9,10 @@ import { usePremium } from "./usePremium";
|
|
|
9
9
|
import type { PurchaseSource } from "../core/SubscriptionConstants";
|
|
10
10
|
import { authPurchaseStateManager } from "../infrastructure/utils/authPurchaseState";
|
|
11
11
|
|
|
12
|
-
export type { PurchaseAuthProvider } from "../infrastructure/utils/authPurchaseState";
|
|
13
|
-
|
|
14
12
|
export const configureAuthProvider = (provider: import("../infrastructure/utils/authPurchaseState").PurchaseAuthProvider): void => {
|
|
15
13
|
authPurchaseStateManager.configure(provider);
|
|
16
14
|
};
|
|
17
15
|
|
|
18
|
-
export const cleanupAuthProvider = (): void => {
|
|
19
|
-
authPurchaseStateManager.cleanup();
|
|
20
|
-
};
|
|
21
|
-
|
|
22
16
|
export const getSavedPurchase = (): { pkg: PurchasesPackage; source: PurchaseSource } | null => {
|
|
23
17
|
return authPurchaseStateManager.getSavedPurchase();
|
|
24
18
|
};
|
|
@@ -27,11 +21,11 @@ export const clearSavedPurchase = (): void => {
|
|
|
27
21
|
authPurchaseStateManager.clearSavedPurchase();
|
|
28
22
|
};
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
interface UseAuthAwarePurchaseParams {
|
|
31
25
|
source?: PurchaseSource;
|
|
32
26
|
}
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
interface UseAuthAwarePurchaseResult {
|
|
35
29
|
handlePurchase: (pkg: PurchasesPackage, source?: PurchaseSource) => Promise<boolean>;
|
|
36
30
|
handleRestore: () => Promise<boolean>;
|
|
37
31
|
executeSavedPurchase: () => Promise<boolean>;
|
|
@@ -4,8 +4,6 @@ import { DEFAULT_REQUIRED_CREDITS, canExecuteAuthAction, canExecutePurchaseActio
|
|
|
4
4
|
import { useSyncedRefs } from "./featureGateRefs";
|
|
5
5
|
import { executeFeatureAction } from "./featureGateActions";
|
|
6
6
|
|
|
7
|
-
export type { UseFeatureGateParams, UseFeatureGateResult } from "./useFeatureGate.types";
|
|
8
|
-
|
|
9
7
|
export function useFeatureGate(params: UseFeatureGateParams): UseFeatureGateResult {
|
|
10
8
|
const {
|
|
11
9
|
isAuthenticated,
|
|
@@ -39,7 +39,7 @@ export const paywallControl = {
|
|
|
39
39
|
getSource: () => paywallState.source,
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
interface UsePaywallVisibilityResult {
|
|
43
43
|
showPaywall: boolean;
|
|
44
44
|
currentSource?: PurchaseSource;
|
|
45
45
|
setShowPaywall: (visible: boolean, source?: PurchaseSource) => void;
|
|
@@ -4,26 +4,3 @@ export function isAuthenticated(userId: string | null | undefined): userId is st
|
|
|
4
4
|
return isDefined(userId) && userId.length > 0;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Requires user to be authenticated, throws if not
|
|
9
|
-
* Type guard that asserts userId is string
|
|
10
|
-
*
|
|
11
|
-
* @param userId - User ID to check
|
|
12
|
-
* @param errorMessage - Custom error message (optional)
|
|
13
|
-
* @throws Error if user is not authenticated
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* function purchaseProduct(userId: string | null) {
|
|
17
|
-
* requireAuthentication(userId); // throws if null/undefined
|
|
18
|
-
* // TypeScript now knows userId is string
|
|
19
|
-
* await purchase(userId);
|
|
20
|
-
* }
|
|
21
|
-
*/
|
|
22
|
-
export function requireAuthentication(
|
|
23
|
-
userId: string | null | undefined,
|
|
24
|
-
errorMessage = "User not authenticated"
|
|
25
|
-
): asserts userId is string {
|
|
26
|
-
if (!isAuthenticated(userId)) {
|
|
27
|
-
throw new Error(errorMessage);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isDefined } from "../../../shared/utils/validators";
|
|
2
2
|
import type { UserCredits } from "../../credits/core/Credits";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
interface SyncState {
|
|
5
5
|
statusLoading: boolean;
|
|
6
6
|
creditsLoading: boolean;
|
|
7
7
|
subscriptionActive: boolean;
|
|
@@ -4,117 +4,6 @@
|
|
|
4
4
|
* Public API for wallet functionality.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
// Config
|
|
8
|
-
export {
|
|
9
|
-
configureWallet,
|
|
10
|
-
getWalletConfig,
|
|
11
|
-
resetWalletConfig,
|
|
12
|
-
type WalletConfiguration,
|
|
13
|
-
} from "./infrastructure/config/walletConfig";
|
|
14
|
-
|
|
15
|
-
// Types
|
|
16
|
-
export type {
|
|
17
|
-
TransactionReason,
|
|
18
|
-
CreditLog,
|
|
19
|
-
TransactionRepositoryConfig,
|
|
20
|
-
TransactionQueryOptions,
|
|
21
|
-
TransactionResult,
|
|
22
|
-
WalletConfig,
|
|
23
|
-
ProductType,
|
|
24
|
-
ProductMetadata,
|
|
25
|
-
ProductMetadataConfig,
|
|
26
|
-
CreditBalance,
|
|
27
|
-
WalletTranslations,
|
|
28
|
-
CreditCostConfig,
|
|
29
|
-
AICreditCosts,
|
|
30
|
-
CreditCostResult,
|
|
31
|
-
} from "./domain/types";
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
DEFAULT_AI_CREDIT_COSTS,
|
|
35
|
-
getCreditCost,
|
|
36
|
-
creditsToDollars,
|
|
37
|
-
createCreditCostConfig,
|
|
38
|
-
} from "./domain/types";
|
|
39
|
-
|
|
40
|
-
// Errors
|
|
41
|
-
export {
|
|
42
|
-
WalletError,
|
|
43
|
-
PaymentValidationError,
|
|
44
|
-
PaymentProviderError,
|
|
45
|
-
DuplicatePaymentError,
|
|
46
|
-
UserValidationError,
|
|
47
|
-
PackageValidationError,
|
|
48
|
-
ReceiptValidationError,
|
|
49
|
-
TransactionError,
|
|
50
|
-
NetworkError,
|
|
51
|
-
CreditLimitError,
|
|
52
|
-
RefundError,
|
|
53
|
-
handleWalletError,
|
|
54
|
-
type WalletErrorCategory,
|
|
55
|
-
} from "./domain/errors/WalletError";
|
|
56
|
-
|
|
57
|
-
// Entities
|
|
58
|
-
export {
|
|
59
|
-
createCreditCostEntity,
|
|
60
|
-
type CreditCostEntity,
|
|
61
|
-
} from "./domain/entities/CreditCost";
|
|
62
|
-
|
|
63
|
-
// Repositories
|
|
64
|
-
export {
|
|
65
|
-
TransactionRepository,
|
|
66
|
-
createTransactionRepository,
|
|
67
|
-
} from "./infrastructure/repositories/transaction";
|
|
68
|
-
|
|
69
|
-
// Services
|
|
70
|
-
export {
|
|
71
|
-
ProductMetadataService,
|
|
72
|
-
createProductMetadataService,
|
|
73
|
-
configureProductMetadataService,
|
|
74
|
-
getProductMetadataService,
|
|
75
|
-
resetProductMetadataService,
|
|
76
|
-
} from "./infrastructure/services/product-metadata";
|
|
77
|
-
|
|
78
|
-
// Hooks
|
|
79
|
-
export {
|
|
80
|
-
useWallet,
|
|
81
|
-
type UseWalletParams,
|
|
82
|
-
type UseWalletResult,
|
|
83
|
-
} from "./presentation/hooks/useWallet";
|
|
84
|
-
|
|
85
|
-
export {
|
|
86
|
-
useTransactionHistory,
|
|
87
|
-
transactionQueryKeys,
|
|
88
|
-
type UseTransactionHistoryParams,
|
|
89
|
-
type UseTransactionHistoryResult,
|
|
90
|
-
} from "./presentation/hooks/useTransactionHistory";
|
|
91
|
-
|
|
92
|
-
export {
|
|
93
|
-
useProductMetadata,
|
|
94
|
-
productMetadataQueryKeys,
|
|
95
|
-
type UseProductMetadataParams,
|
|
96
|
-
type UseProductMetadataResult,
|
|
97
|
-
} from "./presentation/hooks/useProductMetadata";
|
|
98
|
-
|
|
99
|
-
// Components
|
|
100
|
-
export {
|
|
101
|
-
BalanceCard,
|
|
102
|
-
type BalanceCardProps,
|
|
103
|
-
type BalanceCardTranslations,
|
|
104
|
-
} from "./presentation/components/BalanceCard";
|
|
105
|
-
|
|
106
|
-
export {
|
|
107
|
-
TransactionItem,
|
|
108
|
-
type TransactionItemProps,
|
|
109
|
-
type TransactionItemTranslations,
|
|
110
|
-
} from "./presentation/components/TransactionItem";
|
|
111
|
-
|
|
112
|
-
export {
|
|
113
|
-
TransactionList,
|
|
114
|
-
type TransactionListProps,
|
|
115
|
-
type TransactionListTranslations,
|
|
116
|
-
} from "./presentation/components/TransactionList";
|
|
117
|
-
|
|
118
7
|
// Screens
|
|
119
8
|
export {
|
|
120
9
|
WalletScreen,
|
|
@@ -124,4 +13,3 @@ export type {
|
|
|
124
13
|
WalletScreenProps,
|
|
125
14
|
WalletScreenTranslations,
|
|
126
15
|
} from "./presentation/screens/WalletScreen.types";
|
|
127
|
-
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import type { WalletScreenTranslations } from "../../presentation/screens/WalletScreen.types";
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface WalletConfiguration {
|
|
12
12
|
translations: WalletScreenTranslations;
|
|
13
13
|
transactionCollection: string;
|
|
14
14
|
useUserSubcollection: boolean;
|
|
@@ -41,31 +41,9 @@ const DEFAULT_CONFIG: WalletConfiguration = {
|
|
|
41
41
|
|
|
42
42
|
let walletConfig: WalletConfiguration = { ...DEFAULT_CONFIG };
|
|
43
43
|
|
|
44
|
-
/**
|
|
45
|
-
* Configure wallet settings globally
|
|
46
|
-
* Call this once during app initialization
|
|
47
|
-
*/
|
|
48
|
-
export function configureWallet(config: Partial<WalletConfiguration>): void {
|
|
49
|
-
walletConfig = {
|
|
50
|
-
...DEFAULT_CONFIG,
|
|
51
|
-
...config,
|
|
52
|
-
translations: {
|
|
53
|
-
...DEFAULT_CONFIG.translations,
|
|
54
|
-
...config.translations,
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
44
|
/**
|
|
60
45
|
* Get current wallet configuration
|
|
61
46
|
*/
|
|
62
47
|
export function getWalletConfig(): WalletConfiguration {
|
|
63
48
|
return walletConfig;
|
|
64
49
|
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Reset wallet configuration to defaults
|
|
68
|
-
*/
|
|
69
|
-
export function resetWalletConfig(): void {
|
|
70
|
-
walletConfig = { ...DEFAULT_CONFIG };
|
|
71
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { buildCollectionRef, type CollectionConfig } from "../../../../../shared/infrastructure/firestore";
|
|
2
2
|
import type { TransactionRepositoryConfig } from "../../../domain/types/transaction.types";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
function getCollectionConfig(config: TransactionRepositoryConfig): CollectionConfig {
|
|
5
5
|
return {
|
|
6
6
|
collectionName: config.collectionName,
|
|
7
7
|
useUserSubcollection: config.useUserSubcollection ?? false,
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
import type { TransactionRepositoryConfig } from "../../../domain/types/transaction.types";
|
|
2
|
-
import { TransactionRepository } from "./TransactionRepository";
|
|
3
|
-
|
|
4
1
|
export { TransactionRepository } from "./TransactionRepository";
|
|
5
|
-
|
|
6
|
-
export function createTransactionRepository(
|
|
7
|
-
config: TransactionRepositoryConfig
|
|
8
|
-
): TransactionRepository {
|
|
9
|
-
return new TransactionRepository(config);
|
|
10
|
-
}
|
|
@@ -6,8 +6,6 @@ import { transactionItemStyles } from "./TransactionItem.styles";
|
|
|
6
6
|
import type { TransactionItemProps } from "./TransactionItem.types";
|
|
7
7
|
import { defaultDateFormatter, getReasonLabel, getChangePrefix } from "./transactionItemHelpers";
|
|
8
8
|
|
|
9
|
-
export type { TransactionItemTranslations, TransactionItemProps } from "./TransactionItem.types";
|
|
10
|
-
|
|
11
9
|
export const TransactionItem: React.FC<TransactionItemProps> = ({
|
|
12
10
|
transaction,
|
|
13
11
|
translations,
|
|
@@ -2,7 +2,8 @@ import React from "react";
|
|
|
2
2
|
import { View, ScrollView } from "react-native";
|
|
3
3
|
import { useAppDesignTokens, AtomicText, AtomicIcon } from "@umituz/react-native-design-system";
|
|
4
4
|
import type { CreditLog } from "../../domain/types/transaction.types";
|
|
5
|
-
import { TransactionItem
|
|
5
|
+
import { TransactionItem } from "./TransactionItem";
|
|
6
|
+
import type { TransactionItemTranslations } from "./TransactionItem.types";
|
|
6
7
|
import { transactionListStyles } from "./TransactionList.styles";
|
|
7
8
|
import { LoadingState, EmptyState } from "./TransactionListStates";
|
|
8
9
|
import { DEFAULT_TRANSACTION_LIST_MAX_HEIGHT } from "./TransactionList.constants";
|
|
@@ -13,7 +14,7 @@ export interface TransactionListTranslations extends TransactionItemTranslations
|
|
|
13
14
|
loading: string;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
interface TransactionListProps {
|
|
17
18
|
transactions: CreditLog[];
|
|
18
19
|
loading: boolean;
|
|
19
20
|
translations: TransactionListTranslations;
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
} from "../../domain/types/transaction.types";
|
|
9
9
|
import { TransactionRepository } from "../../infrastructure/repositories/transaction";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const transactionQueryKeys = {
|
|
12
12
|
all: ["transactions"] as const,
|
|
13
13
|
user: (userId: string) => ["transactions", userId] as const,
|
|
14
14
|
};
|
|
@@ -18,7 +18,7 @@ export interface UseTransactionHistoryParams {
|
|
|
18
18
|
limit?: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
interface UseTransactionHistoryResult {
|
|
22
22
|
transactions: CreditLog[];
|
|
23
23
|
isLoading: boolean;
|
|
24
24
|
error: Error | null;
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
} from "./useTransactionHistory";
|
|
14
14
|
import type { CreditLog } from "../../domain/types/transaction.types";
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
interface UseWalletParams {
|
|
17
17
|
transactionConfig: UseTransactionHistoryParams["config"];
|
|
18
18
|
transactionLimit?: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
interface UseWalletResult {
|
|
22
22
|
balance: number;
|
|
23
23
|
balanceLoading: boolean;
|
|
24
24
|
transactions: CreditLog[];
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { collection, addDoc, doc } from "firebase/firestore";
|
|
8
8
|
import { getFirestore } from "@umituz/react-native-firebase";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface FeedbackData {
|
|
11
11
|
userId: string | null;
|
|
12
12
|
userEmail: string | null;
|
|
13
13
|
type: string;
|
|
@@ -26,7 +26,7 @@ export interface FeedbackSubmitResult {
|
|
|
26
26
|
* Submit feedback to Firestore
|
|
27
27
|
* Stores under users/{userId}/feedback
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
async function submitFeedback(
|
|
30
30
|
data: FeedbackData
|
|
31
31
|
): Promise<FeedbackSubmitResult> {
|
|
32
32
|
const db = getFirestore();
|
|
@@ -4,7 +4,7 @@ type EventCallback<T = unknown> = (data: T) => void;
|
|
|
4
4
|
* Simple EventBus Implementation
|
|
5
5
|
* Used to decouple services and provide an observer pattern for subscription events.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
class SubscriptionEventBus {
|
|
8
8
|
private static instance: SubscriptionEventBus;
|
|
9
9
|
private listeners: Record<string, EventCallback<any>[]> = {};
|
|
10
10
|
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { Result } from "../../utils/Result";
|
|
7
|
-
import { failure
|
|
7
|
+
import { failure } from "../../utils/Result";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
interface ApiError {
|
|
10
10
|
message: string;
|
|
11
11
|
code: string;
|
|
12
12
|
}
|
|
@@ -14,20 +14,13 @@ export interface ApiError {
|
|
|
14
14
|
/**
|
|
15
15
|
* Create a standard error result
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
function createErrorResult(
|
|
18
18
|
message: string,
|
|
19
19
|
code: string = "UNKNOWN_ERROR"
|
|
20
20
|
): Result<never, ApiError> {
|
|
21
21
|
return failure({ message, code });
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Create a database unavailable error result
|
|
26
|
-
*/
|
|
27
|
-
export function createDbUnavailableResult<T>(): Result<T, ApiError> {
|
|
28
|
-
return createErrorResult("Database not available", "DB_NOT_AVAILABLE");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
24
|
/**
|
|
32
25
|
* Map Error to ApiError result
|
|
33
26
|
*/
|
|
@@ -37,32 +30,3 @@ export function mapErrorToResult<T>(error: unknown): Result<T, ApiError> {
|
|
|
37
30
|
return createErrorResult(message, code);
|
|
38
31
|
}
|
|
39
32
|
|
|
40
|
-
/**
|
|
41
|
-
* Execute async function and return Result
|
|
42
|
-
*/
|
|
43
|
-
export async function executeAsResult<T>(
|
|
44
|
-
fn: () => Promise<T>
|
|
45
|
-
): Promise<Result<T, ApiError>> {
|
|
46
|
-
try {
|
|
47
|
-
const data = await fn();
|
|
48
|
-
return success(data);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
return mapErrorToResult<T>(error);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Validate database availability before executing
|
|
56
|
-
*/
|
|
57
|
-
export async function withDbCheck<T>(
|
|
58
|
-
fn: (db: any) => Promise<T>
|
|
59
|
-
): Promise<Result<T, ApiError>> {
|
|
60
|
-
const { requireFirestore } = require("./collectionUtils");
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const db = requireFirestore();
|
|
64
|
-
return await executeAsResult(() => fn(db));
|
|
65
|
-
} catch (error) {
|
|
66
|
-
return mapErrorToResult<T>(error);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -7,7 +7,7 @@ import { StyleSheet, View, ScrollView, type ViewStyle, type ColorValue } from "r
|
|
|
7
7
|
import { useSafeAreaInsets, type Edge } from "react-native-safe-area-context";
|
|
8
8
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface ScreenLayoutProps {
|
|
11
11
|
children: React.ReactNode;
|
|
12
12
|
scrollable?: boolean;
|
|
13
13
|
edges?: Edge[];
|
|
@@ -1,30 +1,3 @@
|
|
|
1
|
-
export function clamp(value: number, min: number, max: number): number {
|
|
2
|
-
return Math.min(Math.max(value, min), max);
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export function roundTo(value: number, decimals: number = 2): number {
|
|
6
|
-
const multiplier = Math.pow(10, decimals);
|
|
7
|
-
return Math.round(value * multiplier) / multiplier;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function calculatePercentage(value: number, total: number): number {
|
|
11
|
-
if (total === 0) return 0;
|
|
12
|
-
return (value / total) * 100;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function calculatePercentageClamped(value: number, total: number): number {
|
|
16
|
-
return clamp(calculatePercentage(value, total), 0, 100);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isApproximatelyEqual(a: number, b: number, epsilon: number = 0.0001): boolean {
|
|
20
|
-
return Math.abs(a - b) < epsilon;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function safeDivide(numerator: number, denominator: number): number {
|
|
24
|
-
if (denominator === 0) return 0;
|
|
25
|
-
return numerator / denominator;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
1
|
export function calculateRemaining(current: number, cost: number): number {
|
|
29
2
|
return Math.max(0, current - cost);
|
|
30
3
|
}
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Number Utilities
|
|
3
|
-
* Re-exports all number utility modules
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export * from "./numberUtils.aggregate";
|
|
7
|
-
export * from "./numberUtils.core";
|
|
8
|
-
export * from "./numberUtils.format";
|
|
9
|
-
export * from "./numberUtils.math";
|
|
1
|
+
export { calculateRemaining } from "./numberUtils.core";
|
|
@@ -1,69 +1,11 @@
|
|
|
1
|
-
export function isNonEmptyString(value: unknown): value is string {
|
|
2
|
-
return typeof value === "string" && value.trim().length > 0;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
1
|
export function isValidNumber(value: unknown): value is number {
|
|
6
2
|
return typeof value === "number" && !isNaN(value) && isFinite(value);
|
|
7
3
|
}
|
|
8
4
|
|
|
9
|
-
export function isPositiveNumber(value: unknown): value is number {
|
|
10
|
-
return isValidNumber(value) && value > 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
5
|
export function isNonNegativeNumber(value: unknown): value is number {
|
|
14
6
|
return isValidNumber(value) && value >= 0;
|
|
15
7
|
}
|
|
16
8
|
|
|
17
|
-
export function isInteger(value: unknown): value is number {
|
|
18
|
-
return isValidNumber(value) && Number.isInteger(value);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function isValidDate(value: unknown): boolean {
|
|
22
|
-
if (value instanceof Date) {
|
|
23
|
-
return !isNaN(value.getTime());
|
|
24
|
-
}
|
|
25
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
26
|
-
const d = new Date(value);
|
|
27
|
-
return !isNaN(d.getTime());
|
|
28
|
-
}
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function isValidEmail(value: unknown): value is string {
|
|
33
|
-
if (!isNonEmptyString(value)) return false;
|
|
34
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
35
|
-
return emailRegex.test(value);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function isValidUrl(value: unknown): value is string {
|
|
39
|
-
if (!isNonEmptyString(value)) return false;
|
|
40
|
-
try {
|
|
41
|
-
new URL(value);
|
|
42
|
-
return true;
|
|
43
|
-
} catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function isValueInRange(
|
|
49
|
-
value: unknown,
|
|
50
|
-
min: number,
|
|
51
|
-
max: number,
|
|
52
|
-
inclusive: boolean = true
|
|
53
|
-
): value is number {
|
|
54
|
-
if (!isValidNumber(value)) return false;
|
|
55
|
-
if (inclusive) return value >= min && value <= max;
|
|
56
|
-
return value > min && value < max;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function isNonEmptyArray<T>(value: unknown): value is [T, ...T[]] {
|
|
60
|
-
return Array.isArray(value) && value.length > 0;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
64
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
9
|
export function isDefined<T>(value: T | null | undefined): value is T {
|
|
68
10
|
return value !== null && value !== undefined;
|
|
69
11
|
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plan Entity
|
|
3
|
-
* Represents a subscription plan with credits and pricing
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export type PlanType = "weekly" | "monthly" | "yearly" | "lifetime" | "custom";
|
|
7
|
-
|
|
8
|
-
export interface Plan {
|
|
9
|
-
readonly id: string;
|
|
10
|
-
readonly type: PlanType;
|
|
11
|
-
readonly credits: number;
|
|
12
|
-
readonly price: number;
|
|
13
|
-
readonly currency: string;
|
|
14
|
-
readonly labelKey: string;
|
|
15
|
-
readonly descriptionKey?: string;
|
|
16
|
-
readonly isBestValue?: boolean;
|
|
17
|
-
readonly isPopular?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface PlanMetadata {
|
|
21
|
-
readonly cost: number;
|
|
22
|
-
readonly profit: number;
|
|
23
|
-
readonly profitMargin: number;
|
|
24
|
-
readonly pricePerCredit: number;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const calculatePlanMetadata = (
|
|
28
|
-
plan: Plan,
|
|
29
|
-
costPerCredit: number,
|
|
30
|
-
commissionRate: number = 0.30
|
|
31
|
-
): PlanMetadata => {
|
|
32
|
-
const totalCost = plan.credits * costPerCredit;
|
|
33
|
-
const netRevenue = plan.price * (1 - commissionRate);
|
|
34
|
-
const profit = netRevenue - totalCost;
|
|
35
|
-
const profitMargin = plan.price > 0 ? (profit / plan.price) * 100 : 0;
|
|
36
|
-
const pricePerCredit = plan.credits > 0 ? plan.price / plan.credits : 0;
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
cost: totalCost,
|
|
40
|
-
profit,
|
|
41
|
-
profitMargin,
|
|
42
|
-
pricePerCredit,
|
|
43
|
-
};
|
|
44
|
-
};
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subscription Configuration Value Object
|
|
3
|
-
* Defines app-specific subscription plans and settings
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Plan } from "../entities/Plan";
|
|
7
|
-
|
|
8
|
-
export interface ConfigTranslations {
|
|
9
|
-
readonly title: string;
|
|
10
|
-
readonly subtitle?: string;
|
|
11
|
-
readonly creditsLabel: string;
|
|
12
|
-
readonly creditsRemaining: string;
|
|
13
|
-
readonly creditsTotal: string;
|
|
14
|
-
readonly upgradeButton: string;
|
|
15
|
-
readonly manageButton: string;
|
|
16
|
-
readonly restoreButton: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface Config {
|
|
20
|
-
readonly plans: readonly Plan[];
|
|
21
|
-
readonly collectionName: string;
|
|
22
|
-
readonly entitlementId: string;
|
|
23
|
-
readonly translations: ConfigTranslations;
|
|
24
|
-
readonly showCreditDetails?: boolean;
|
|
25
|
-
readonly allowRestore?: boolean;
|
|
26
|
-
readonly costPerCredit?: number;
|
|
27
|
-
readonly commissionRate?: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const DEFAULT_TRANSLATIONS: ConfigTranslations = {
|
|
31
|
-
title: "subscription.title",
|
|
32
|
-
subtitle: "subscription.subtitle",
|
|
33
|
-
creditsLabel: "subscription.credits",
|
|
34
|
-
creditsRemaining: "subscription.creditsRemaining",
|
|
35
|
-
creditsTotal: "subscription.creditsTotal",
|
|
36
|
-
upgradeButton: "subscription.upgrade",
|
|
37
|
-
manageButton: "subscription.manage",
|
|
38
|
-
restoreButton: "subscription.restore",
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const DEFAULT_CONFIG: Partial<Config> = {
|
|
42
|
-
collectionName: "credits",
|
|
43
|
-
entitlementId: "premium",
|
|
44
|
-
translations: DEFAULT_TRANSLATIONS,
|
|
45
|
-
showCreditDetails: true,
|
|
46
|
-
allowRestore: true,
|
|
47
|
-
costPerCredit: 0.04,
|
|
48
|
-
commissionRate: 0.30,
|
|
49
|
-
};
|