@umituz/react-native-subscription 2.14.16 → 2.14.18

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.
@@ -3,69 +3,71 @@
3
3
  * Displays list of credit usages
4
4
  */
5
5
 
6
- import React from "react";
7
- import { View, Text, StyleSheet } from "react-native";
8
- import { useAppDesignTokens } from "@umituz/react-native-design-system";
6
+ import React, { useMemo } from "react";
7
+ import { View, StyleSheet } from "react-native";
8
+ import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
9
9
  import { CreditItem } from "./CreditItem";
10
- import type { CreditInfo } from "../../components/details/PremiumDetailsCard";
11
-
12
- interface CreditsListProps {
13
- credits: CreditInfo[];
14
- title?: string;
15
- description?: string;
16
- remainingLabel?: string;
17
- }
10
+ import type { CreditsListProps } from "../../types/SubscriptionDetailTypes";
18
11
 
19
12
  export const CreditsList: React.FC<CreditsListProps> = ({
20
- credits,
21
- title,
22
- description,
23
- remainingLabel,
13
+ credits,
14
+ title,
15
+ description,
16
+ remainingLabel,
24
17
  }) => {
25
- const tokens = useAppDesignTokens();
18
+ const tokens = useAppDesignTokens();
26
19
 
27
- return (
28
- <View style={[styles.container, { backgroundColor: tokens.colors.surface }]}>
29
- {title && (
30
- <Text style={[styles.title, { color: tokens.colors.textPrimary }]}>
31
- {title}
32
- </Text>
33
- )}
34
- {description && (
35
- <Text style={[styles.description, { color: tokens.colors.textSecondary }]}>
36
- {description}
37
- </Text>
38
- )}
39
- <View style={styles.list}>
40
- {credits.map((credit) => (
41
- <CreditItem
42
- key={credit.id}
43
- label={credit.label}
44
- current={credit.current}
45
- total={credit.total}
46
- remainingLabel={remainingLabel}
47
- />
48
- ))}
49
- </View>
50
- </View>
51
- );
52
- };
20
+ const styles = useMemo(
21
+ () =>
22
+ StyleSheet.create({
23
+ container: {
24
+ borderRadius: tokens.borderRadius.lg,
25
+ padding: tokens.spacing.lg,
26
+ gap: tokens.spacing.lg,
27
+ backgroundColor: tokens.colors.surface,
28
+ },
29
+ title: {
30
+ fontWeight: "700",
31
+ },
32
+ description: {
33
+ marginTop: -tokens.spacing.sm,
34
+ },
35
+ list: {
36
+ gap: tokens.spacing.lg,
37
+ },
38
+ }),
39
+ [tokens]
40
+ );
53
41
 
54
- const styles = StyleSheet.create({
55
- container: {
56
- borderRadius: 16,
57
- padding: 20,
58
- gap: 16,
59
- },
60
- title: {
61
- fontSize: 18,
62
- fontWeight: "700",
63
- },
64
- description: {
65
- fontSize: 14,
66
- marginTop: -8,
67
- },
68
- list: {
69
- gap: 16,
70
- },
71
- });
42
+ return (
43
+ <View style={styles.container}>
44
+ {title && (
45
+ <AtomicText
46
+ type="titleMedium"
47
+ style={[styles.title, { color: tokens.colors.textPrimary }]}
48
+ >
49
+ {title}
50
+ </AtomicText>
51
+ )}
52
+ {description && (
53
+ <AtomicText
54
+ type="bodySmall"
55
+ style={[styles.description, { color: tokens.colors.textSecondary }]}
56
+ >
57
+ {description}
58
+ </AtomicText>
59
+ )}
60
+ <View style={styles.list}>
61
+ {credits.map((credit) => (
62
+ <CreditItem
63
+ key={credit.id}
64
+ label={credit.label}
65
+ current={credit.current}
66
+ total={credit.total}
67
+ remainingLabel={remainingLabel}
68
+ />
69
+ ))}
70
+ </View>
71
+ </View>
72
+ );
73
+ };
@@ -4,118 +4,122 @@
4
4
  * Only visible in __DEV__ mode
5
5
  */
6
6
 
7
- import React from "react";
7
+ import React, { useMemo } from "react";
8
8
  import { View, TouchableOpacity, StyleSheet } from "react-native";
9
9
  import { AtomicText, useAppDesignTokens } from "@umituz/react-native-design-system";
10
+ import type { DevTestSectionProps } from "../../types/SubscriptionDetailTypes";
10
11
 
11
- export interface DevTestActions {
12
- onTestRenewal: () => Promise<void>;
13
- onCheckCredits: () => void;
14
- onTestDuplicate: () => Promise<void>;
12
+ export type { DevTestActions, DevTestSectionProps } from "../../types/SubscriptionDetailTypes";
13
+
14
+ /** Dev test button translations */
15
+ export interface DevTestTranslations {
16
+ title: string;
17
+ testRenewal: string;
18
+ checkCredits: string;
19
+ testDuplicate: string;
15
20
  }
16
21
 
17
- export interface DevTestSectionProps {
18
- actions: DevTestActions;
19
- title?: string;
22
+ export interface DevTestSectionWithTranslationsProps extends DevTestSectionProps {
23
+ translations?: DevTestTranslations;
20
24
  }
21
25
 
22
- export const DevTestSection: React.FC<DevTestSectionProps> = ({
26
+ export const DevTestSection: React.FC<DevTestSectionWithTranslationsProps> = ({
23
27
  actions,
24
- title = "🧪 Developer Testing",
28
+ title,
29
+ translations,
25
30
  }) => {
26
31
  const tokens = useAppDesignTokens();
27
32
 
33
+ const styles = useMemo(
34
+ () =>
35
+ StyleSheet.create({
36
+ container: {
37
+ padding: tokens.spacing.lg,
38
+ gap: tokens.spacing.md,
39
+ borderTopWidth: 1,
40
+ backgroundColor: tokens.colors.surfaceSecondary,
41
+ borderTopColor: tokens.colors.border,
42
+ },
43
+ title: {
44
+ fontWeight: "600",
45
+ marginBottom: tokens.spacing.xs,
46
+ },
47
+ button: {
48
+ paddingVertical: tokens.spacing.md,
49
+ paddingHorizontal: tokens.spacing.lg,
50
+ borderRadius: tokens.borderRadius.md,
51
+ alignItems: "center",
52
+ },
53
+ primaryButton: {
54
+ backgroundColor: tokens.colors.primary,
55
+ },
56
+ secondaryButton: {
57
+ backgroundColor: tokens.colors.surfaceSecondary,
58
+ borderWidth: 1,
59
+ borderColor: tokens.colors.border,
60
+ },
61
+ buttonText: {
62
+ fontWeight: "500",
63
+ },
64
+ }),
65
+ [tokens]
66
+ );
67
+
28
68
  if (!__DEV__) {
29
69
  return null;
30
70
  }
31
71
 
72
+ const displayTitle = title || translations?.title;
73
+ const renewalText = translations?.testRenewal || "Test Auto-Renewal";
74
+ const creditsText = translations?.checkCredits || "Check Credits";
75
+ const duplicateText = translations?.testDuplicate || "Test Duplicate Protection";
76
+
32
77
  return (
33
- <View
34
- style={[
35
- styles.container,
36
- {
37
- backgroundColor: tokens.colors.surfaceSecondary,
38
- borderTopColor: tokens.colors.border,
39
- },
40
- ]}
41
- >
42
- <AtomicText
43
- type="titleMedium"
44
- style={[styles.title, { color: tokens.colors.textPrimary }]}
45
- >
46
- {title}
47
- </AtomicText>
78
+ <View style={styles.container}>
79
+ {displayTitle && (
80
+ <AtomicText
81
+ type="titleMedium"
82
+ style={[styles.title, { color: tokens.colors.textPrimary }]}
83
+ >
84
+ {displayTitle}
85
+ </AtomicText>
86
+ )}
48
87
 
49
88
  <TouchableOpacity
50
- style={[styles.button, { backgroundColor: tokens.colors.primary }]}
89
+ style={[styles.button, styles.primaryButton]}
51
90
  onPress={actions.onTestRenewal}
52
91
  >
53
92
  <AtomicText
54
93
  type="bodyMedium"
55
94
  style={[styles.buttonText, { color: tokens.colors.onPrimary }]}
56
95
  >
57
- ⚡ Test Auto-Renewal (Add Credits)
96
+ {renewalText}
58
97
  </AtomicText>
59
98
  </TouchableOpacity>
60
99
 
61
100
  <TouchableOpacity
62
- style={[
63
- styles.button,
64
- {
65
- backgroundColor: tokens.colors.surfaceSecondary,
66
- borderWidth: 1,
67
- borderColor: tokens.colors.border,
68
- },
69
- ]}
101
+ style={[styles.button, styles.secondaryButton]}
70
102
  onPress={actions.onCheckCredits}
71
103
  >
72
104
  <AtomicText
73
105
  type="bodyMedium"
74
106
  style={[styles.buttonText, { color: tokens.colors.textPrimary }]}
75
107
  >
76
- 📊 Check Current Credits
108
+ {creditsText}
77
109
  </AtomicText>
78
110
  </TouchableOpacity>
79
111
 
80
112
  <TouchableOpacity
81
- style={[
82
- styles.button,
83
- {
84
- backgroundColor: tokens.colors.surfaceSecondary,
85
- borderWidth: 1,
86
- borderColor: tokens.colors.border,
87
- },
88
- ]}
113
+ style={[styles.button, styles.secondaryButton]}
89
114
  onPress={actions.onTestDuplicate}
90
115
  >
91
116
  <AtomicText
92
117
  type="bodyMedium"
93
118
  style={[styles.buttonText, { color: tokens.colors.textPrimary }]}
94
119
  >
95
- 🔒 Test Duplicate Protection
120
+ {duplicateText}
96
121
  </AtomicText>
97
122
  </TouchableOpacity>
98
123
  </View>
99
124
  );
100
125
  };
101
-
102
- const styles = StyleSheet.create({
103
- container: {
104
- padding: 16,
105
- gap: 12,
106
- borderTopWidth: 1,
107
- },
108
- title: {
109
- fontWeight: "600",
110
- marginBottom: 4,
111
- },
112
- button: {
113
- paddingVertical: 12,
114
- paddingHorizontal: 16,
115
- borderRadius: 8,
116
- alignItems: "center",
117
- },
118
- buttonText: {
119
- fontWeight: "500",
120
- },
121
- });
@@ -1,77 +1,51 @@
1
1
  /**
2
2
  * Subscription Actions Component
3
- * Displays action buttons for subscription management
3
+ * Displays upgrade button for non-premium users
4
4
  */
5
5
 
6
- import React from "react";
6
+ import React, { useMemo } from "react";
7
7
  import { View, StyleSheet, TouchableOpacity } from "react-native";
8
8
  import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
9
-
10
- interface SubscriptionActionsProps {
11
- isPremium: boolean;
12
- manageButtonLabel?: string;
13
- upgradeButtonLabel?: string;
14
- onManage?: () => void;
15
- onUpgrade?: () => void;
16
- }
9
+ import type { SubscriptionActionsProps } from "../../types/SubscriptionDetailTypes";
17
10
 
18
11
  export const SubscriptionActions: React.FC<SubscriptionActionsProps> = ({
19
- isPremium,
20
- manageButtonLabel,
21
- upgradeButtonLabel,
22
- onManage,
23
- onUpgrade,
12
+ isPremium,
13
+ upgradeButtonLabel,
14
+ onUpgrade,
24
15
  }) => {
25
- const tokens = useAppDesignTokens();
16
+ const tokens = useAppDesignTokens();
26
17
 
27
- return (
28
- <View style={styles.container}>
29
- {isPremium && onManage && manageButtonLabel && (
30
- <TouchableOpacity
31
- style={[
32
- styles.secondaryButton,
33
- { backgroundColor: tokens.colors.surfaceSecondary },
34
- ]}
35
- onPress={onManage}
36
- >
37
- <AtomicText
38
- type="titleMedium"
39
- style={{ color: tokens.colors.textPrimary, fontWeight: "600" }}
40
- >
41
- {manageButtonLabel}
42
- </AtomicText>
43
- </TouchableOpacity>
44
- )}
45
- {!isPremium && onUpgrade && upgradeButtonLabel && (
46
- <TouchableOpacity
47
- style={[styles.primaryButton, { backgroundColor: tokens.colors.primary }]}
48
- onPress={onUpgrade}
49
- >
50
- <AtomicText
51
- type="titleMedium"
52
- style={{ color: tokens.colors.onPrimary, fontWeight: "700" }}
53
- >
54
- {upgradeButtonLabel}
55
- </AtomicText>
56
- </TouchableOpacity>
57
- )}
58
- </View>
59
- );
60
- };
18
+ const styles = useMemo(
19
+ () =>
20
+ StyleSheet.create({
21
+ container: {
22
+ paddingBottom: tokens.spacing.xl,
23
+ },
24
+ primaryButton: {
25
+ paddingVertical: tokens.spacing.md,
26
+ borderRadius: tokens.borderRadius.lg,
27
+ alignItems: "center",
28
+ backgroundColor: tokens.colors.primary,
29
+ },
30
+ buttonText: {
31
+ color: tokens.colors.onPrimary,
32
+ fontWeight: "700",
33
+ },
34
+ }),
35
+ [tokens]
36
+ );
61
37
 
62
- const styles = StyleSheet.create({
63
- container: {
64
- gap: 12,
65
- paddingBottom: 32,
66
- },
67
- primaryButton: {
68
- paddingVertical: 16,
69
- borderRadius: 12,
70
- alignItems: "center",
71
- },
72
- secondaryButton: {
73
- paddingVertical: 16,
74
- borderRadius: 12,
75
- alignItems: "center",
76
- },
77
- });
38
+ if (isPremium || !onUpgrade || !upgradeButtonLabel) {
39
+ return null;
40
+ }
41
+
42
+ return (
43
+ <View style={styles.container}>
44
+ <TouchableOpacity style={styles.primaryButton} onPress={onUpgrade}>
45
+ <AtomicText type="titleMedium" style={styles.buttonText}>
46
+ {upgradeButtonLabel}
47
+ </AtomicText>
48
+ </TouchableOpacity>
49
+ </View>
50
+ );
51
+ };