related-ui-components 1.7.6 → 1.7.7

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,58 @@
1
+ import React from "react";
2
+ import { ImageSourcePropType, StyleProp, ViewStyle } from "react-native";
3
+ import { BottomSheetProps } from "@gorhom/bottom-sheet";
4
+ type Props = {
5
+ visible: boolean;
6
+ onClose: () => void;
7
+ code: string;
8
+ amount?: number;
9
+ expiry?: string;
10
+ image?: ImageSourcePropType;
11
+ title?: string;
12
+ currency?: string;
13
+ codeReadyText?: string;
14
+ qrCodeLabel?: string;
15
+ barCodeLabel?: string;
16
+ myVouchersButtonText?: string;
17
+ onMyVouchersButtonPress?: () => void;
18
+ onCopyCode?: (copiedCode: string) => void;
19
+ showAppleWalletButton?: boolean;
20
+ appleWalletButtonText?: string;
21
+ onAppleWalletButtonPress?: () => void;
22
+ appleWalletIconSource?: ImageSourcePropType;
23
+ qrCodeSize?: number;
24
+ activeTabColors?: string[];
25
+ inactiveTabBackgroundColor?: string;
26
+ inactiveTabBorderColor?: string;
27
+ inactiveTabTextColor?: string;
28
+ primaryButtonColors?: string[];
29
+ allowBarcodeSwitch?: boolean;
30
+ renderBarcodeComponent?: (code: string) => React.ReactNode;
31
+ renderCopyIcon?: () => React.ReactNode;
32
+ amountIconComponent?: React.ReactNode;
33
+ expiryIconComponent?: React.ReactNode;
34
+ snapPoints?: string[];
35
+ sheetBackgroundStyle?: StyleProp<ViewStyle>;
36
+ sheetHandleStyle?: StyleProp<ViewStyle>;
37
+ backdropPressBehavior?: "close" | "none" | number;
38
+ bottomSheetOverrideProps?: Partial<Omit<BottomSheetProps, "children" | "snapPoints" | "index" | "onClose" | "enablePanDownToClose" | "backgroundStyle" | "handleIndicatorStyle" | "backdropComponent">>;
39
+ tabGradientStart?: {
40
+ x: number;
41
+ y: number;
42
+ };
43
+ tabGradientEnd?: {
44
+ x: number;
45
+ y: number;
46
+ };
47
+ primaryButtonGradientStart?: {
48
+ x: number;
49
+ y: number;
50
+ };
51
+ primaryButtonGradientEnd?: {
52
+ x: number;
53
+ y: number;
54
+ };
55
+ };
56
+ declare const RedeemedVoucherSheet: React.FC<Props>;
57
+ export default RedeemedVoucherSheet;
58
+ //# sourceMappingURL=RedeemedVoucherSheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedeemedVoucherSheet.d.ts","sourceRoot":"","sources":["../../../../../src/components/RedeemedVoucher/RedeemedVoucherSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAOL,mBAAmB,EACnB,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAoB,EAElB,gBAAgB,EAGjB,MAAM,sBAAsB,CAAC;AAO9B,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAE5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;IACtC,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3D,cAAc,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACvC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACtC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5C,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACxC,qBAAqB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClD,wBAAwB,CAAC,EAAE,OAAO,CAChC,IAAI,CACF,gBAAgB,EACd,UAAU,GACV,YAAY,GACZ,OAAO,GACP,SAAS,GACT,sBAAsB,GACtB,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,CACtB,CACF,CAAC;IACF,gBAAgB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,cAAc,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,0BAA0B,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,wBAAwB,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD,CAAC;AAEF,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA8RzC,CAAC;AAsLF,eAAe,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "related-ui-components",
3
3
  "main": "./src/index.ts",
4
- "version": "1.7.6",
4
+ "version": "1.7.7",
5
5
  "scripts": {
6
6
  "start": "expo start",
7
7
  "reset-project": "node ./scripts/reset-project.js",
@@ -42,12 +42,14 @@
42
42
  "react-native-calendars": "^1.1310.0",
43
43
  "react-native-gesture-handler": "~2.20.2",
44
44
  "react-native-modal": "^14.0.0-rc.1",
45
+ "react-native-qrcode-svg": "^6.3.15",
45
46
  "react-native-reanimated": "^3.16.1",
46
47
  "react-native-safe-area-context": "4.12.0",
47
48
  "react-native-screens": "~4.4.0",
48
49
  "react-native-svg": "15.8.0",
49
50
  "react-native-web": "~0.19.13",
50
- "react-native-webview": "13.12.5"
51
+ "react-native-webview": "13.12.5",
52
+ "expo-clipboard": "~7.0.1"
51
53
  },
52
54
  "devDependencies": {
53
55
  "@babel/core": "^7.25.2",
package/src/app.tsx CHANGED
@@ -4,6 +4,8 @@ import { FilterResult, Filters, Popup, UnlockRewards } from "./components";
4
4
  import BRANDS from "./constants/BRANDS";
5
5
  import { Ionicons } from "@expo/vector-icons";
6
6
  import { useTheme } from "./theme";
7
+ import RedeemedVoucherSheet from "./components/RedeemedVoucher/RedeemedVoucherSheet";
8
+ import { GestureHandlerRootView } from "react-native-gesture-handler";
7
9
 
8
10
  const MyScreen = () => {
9
11
  const [isFilterVisible, setIsFilterVisible] = useState(false);
@@ -83,25 +85,23 @@ const MyScreen = () => {
83
85
 
84
86
  return (
85
87
  <>
86
- <Popup
87
- visible={isFilterVisible}
88
- onClose={() => setIsFilterVisible(false)}
89
- showCloseIcon={true}
90
- title="ترقية إلى النسخة المميزة"
91
- subtitle="استمتع بمزايا حصرية"
92
- content="احصل على جميع الميزات المتقدمة والمحتوى الحصري بدون إعلانات. اشترك الآن واستمتع بتجربة كاملة مع تحديثات مجانية لمدة عام كامل."
93
- primaryButtonText="ترقية الآن"
94
- secondaryButtonText="ليس الآن"
95
- // onPrimaryButtonPress={handleUpgrade}
96
- // onSecondaryButtonPress={handleDismiss}
97
- isRTL={true}
98
- >
99
-
100
- <UnlockRewards rewards={rewardsData}></UnlockRewards>
101
- </Popup>
102
- <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
103
- <Button title="Show Filters" onPress={() => setIsFilterVisible(true)} />
104
- </View>
88
+ <GestureHandlerRootView>
89
+ <RedeemedVoucherSheet
90
+ visible={true}
91
+ onClose={() => {}}
92
+ code="0000P78SHV50KK"
93
+ // amount={100}
94
+ expiry="22/01/2025"
95
+ currency="USD"
96
+ title="Voucher Activated!"
97
+ // primaryButtonColors={["red", "blue"]}
98
+ onMyVouchersButtonPress={() => console.log("My Vouchers pressed")}
99
+ onCopyCode={(code) => console.log("Copied:", code)}
100
+ // To use custom icons:
101
+ // amountIconComponent={<Image source={YourCustomAmountIcon} style={{width: 20, height: 20, marginRight: 5}} />}
102
+ // renderCopyIcon={() => <Text style={{fontSize: 22, color: 'blue'}}>COPY</Text>}
103
+ />
104
+ </GestureHandlerRootView>
105
105
  </>
106
106
  );
107
107
  };
@@ -0,0 +1,547 @@
1
+ import React, { useCallback, useMemo, useRef } from "react";
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ Image,
8
+ Pressable,
9
+ ImageSourcePropType,
10
+ StyleProp,
11
+ ViewStyle,
12
+ } from "react-native";
13
+ import BottomSheet, {
14
+ BottomSheetView,
15
+ BottomSheetProps,
16
+ BottomSheetBackdrop,
17
+ BottomSheetBackdropProps,
18
+ } from "@gorhom/bottom-sheet";
19
+ import QRCode from "react-native-qrcode-svg";
20
+ import { LinearGradient } from "expo-linear-gradient";
21
+ import * as Clipboard from "expo-clipboard";
22
+ import { ThemeType, useTheme } from "@/theme";
23
+ import { Ionicons } from "@expo/vector-icons";
24
+
25
+ type Props = {
26
+ visible: boolean;
27
+ onClose: () => void;
28
+ code: string;
29
+ amount?: number;
30
+ expiry?: string;
31
+ image?: ImageSourcePropType;
32
+
33
+ title?: string;
34
+ currency?: string;
35
+ codeReadyText?: string;
36
+ qrCodeLabel?: string;
37
+ barCodeLabel?: string;
38
+ myVouchersButtonText?: string;
39
+ onMyVouchersButtonPress?: () => void;
40
+ onCopyCode?: (copiedCode: string) => void;
41
+ showAppleWalletButton?: boolean;
42
+ appleWalletButtonText?: string;
43
+ onAppleWalletButtonPress?: () => void;
44
+ appleWalletIconSource?: ImageSourcePropType;
45
+ qrCodeSize?: number;
46
+ activeTabColors?: string[];
47
+ inactiveTabBackgroundColor?: string;
48
+ inactiveTabBorderColor?: string;
49
+ inactiveTabTextColor?: string;
50
+ primaryButtonColors?: string[];
51
+ allowBarcodeSwitch?: boolean;
52
+ renderBarcodeComponent?: (code: string) => React.ReactNode;
53
+ renderCopyIcon?: () => React.ReactNode;
54
+ amountIconComponent?: React.ReactNode;
55
+ expiryIconComponent?: React.ReactNode;
56
+ snapPoints?: string[];
57
+ sheetBackgroundStyle?: StyleProp<ViewStyle>;
58
+ sheetHandleStyle?: StyleProp<ViewStyle>;
59
+ backdropPressBehavior?: "close" | "none" | number;
60
+ bottomSheetOverrideProps?: Partial<
61
+ Omit<
62
+ BottomSheetProps,
63
+ | "children"
64
+ | "snapPoints"
65
+ | "index"
66
+ | "onClose"
67
+ | "enablePanDownToClose"
68
+ | "backgroundStyle"
69
+ | "handleIndicatorStyle"
70
+ | "backdropComponent"
71
+ >
72
+ >;
73
+ tabGradientStart?: { x: number; y: number };
74
+ tabGradientEnd?: { x: number; y: number };
75
+ primaryButtonGradientStart?: { x: number; y: number };
76
+ primaryButtonGradientEnd?: { x: number; y: number };
77
+ };
78
+
79
+ const RedeemedVoucherSheet: React.FC<Props> = (props) => {
80
+ const { theme } = useTheme();
81
+ const styles = useMemo(() => getStyles(theme), [theme]);
82
+
83
+ const defaultActiveTabColors = useMemo(
84
+ () =>
85
+ theme.primary
86
+ ? [theme.primary, theme.primaryVariant || theme.primary]
87
+ : ["#F97794", "#623AA2"],
88
+ [theme],
89
+ );
90
+
91
+ const defaultPrimaryButtonColors = useMemo(
92
+ () =>
93
+ defaultActiveTabColors,
94
+ [theme, defaultActiveTabColors],
95
+ );
96
+
97
+ const defaultInactiveTabBorderColor = useMemo(
98
+ () => theme.primary || defaultActiveTabColors[1] || "#623AA2",
99
+ [theme, defaultActiveTabColors],
100
+ );
101
+
102
+ const defaultInactiveTabTextColor = useMemo(
103
+ () => theme.primary || defaultActiveTabColors[1] || "#623AA2",
104
+ [theme, defaultActiveTabColors],
105
+ );
106
+
107
+
108
+ const {
109
+ visible,
110
+ onClose,
111
+ code,
112
+ amount,
113
+ expiry,
114
+ image, // Now directly from props
115
+ title = "Successfully Redeemed!",
116
+ currency = "SAR",
117
+ codeReadyText = "Your Code Is Ready!",
118
+ qrCodeLabel = "QR Code",
119
+ barCodeLabel = "Bar Code",
120
+ myVouchersButtonText = "My Vouchers",
121
+ onMyVouchersButtonPress,
122
+ onCopyCode,
123
+ showAppleWalletButton = true,
124
+ appleWalletButtonText = "Add to Apple Wallet",
125
+ onAppleWalletButtonPress,
126
+ appleWalletIconSource, // Now directly from props
127
+ qrCodeSize = 120,
128
+ activeTabColors = defaultActiveTabColors,
129
+ inactiveTabBackgroundColor = theme.surface || "#FFFFFF",
130
+ inactiveTabBorderColor: propInactiveTabBorderColor,
131
+ inactiveTabTextColor: propInactiveTabTextColor,
132
+ primaryButtonColors = defaultPrimaryButtonColors,
133
+ allowBarcodeSwitch = true,
134
+ renderBarcodeComponent,
135
+ renderCopyIcon,
136
+ amountIconComponent,
137
+ expiryIconComponent,
138
+ snapPoints: propSnapPoints,
139
+ sheetBackgroundStyle,
140
+ sheetHandleStyle,
141
+ backdropPressBehavior = "close",
142
+ bottomSheetOverrideProps,
143
+ tabGradientStart = { x: 0, y: 0.5 },
144
+ tabGradientEnd = { x: 1, y: 0.5 },
145
+ primaryButtonGradientStart = { x: 0, y: 0.5 },
146
+ primaryButtonGradientEnd = { x: 1, y: 0.5 },
147
+ } = props;
148
+
149
+
150
+ const finalInactiveTabBorderColor = propInactiveTabBorderColor || defaultInactiveTabBorderColor;
151
+ const finalInactiveTabTextColor = propInactiveTabTextColor || defaultInactiveTabTextColor;
152
+
153
+
154
+ const bottomSheetRef = useRef<BottomSheet>(null);
155
+ const finalSnapPoints = useMemo(
156
+ () => propSnapPoints || ["75%"],
157
+ [propSnapPoints],
158
+ );
159
+
160
+ const [tab, setTab] = React.useState<"qr" | "bar">("qr");
161
+
162
+ const handleCopyCode = async () => {
163
+ await Clipboard.setStringAsync(code);
164
+ if (onCopyCode) {
165
+ onCopyCode(code);
166
+ }
167
+ };
168
+
169
+ // Custom backdrop component
170
+ const renderBackdrop = useCallback(
171
+ (backdropProps: BottomSheetBackdropProps) => (
172
+ <BottomSheetBackdrop
173
+ {...backdropProps}
174
+ disappearsOnIndex={-1}
175
+ appearsOnIndex={0}
176
+ pressBehavior={backdropPressBehavior}
177
+ opacity={0.5}
178
+ style={[
179
+ backdropProps.style,
180
+ { backgroundColor: "rgba(0,0,0,0.5)" },
181
+ ]}
182
+ />
183
+ ),
184
+ [backdropPressBehavior, theme],
185
+ );
186
+ const iconSize = 24;
187
+ const defaultAmountIcon = (
188
+ <Ionicons style={styles.defaultIconStyle} name="cash-outline" size={iconSize} color={theme.onSurface} />
189
+ );
190
+
191
+ const defaultExpiryIcon = (
192
+ <Ionicons style={styles.defaultIconStyle} name="time-outline" size={iconSize} color={theme.onSurface} />
193
+ );
194
+
195
+ const defaultCopyIcon = (
196
+ <Ionicons
197
+ name="copy-outline"
198
+ size={iconSize}
199
+ color={finalInactiveTabTextColor}
200
+ style={styles.copyIconText}
201
+ />
202
+ );
203
+
204
+
205
+ return (
206
+ <BottomSheet
207
+ ref={bottomSheetRef}
208
+ index={visible ? 0 : -1}
209
+ snapPoints={finalSnapPoints}
210
+ enablePanDownToClose
211
+ onClose={onClose}
212
+ backgroundStyle={[styles.sheetBackgroundBase, sheetBackgroundStyle]}
213
+ handleIndicatorStyle={[styles.handleBase, sheetHandleStyle]}
214
+ backdropComponent={renderBackdrop}
215
+ {...bottomSheetOverrideProps}
216
+ >
217
+ <BottomSheetView style={styles.container}>
218
+ {image && (
219
+ <Image source={image} style={styles.giftImage} />
220
+ )}
221
+ <Text style={styles.title}>{title}</Text>
222
+
223
+ <View style={styles.infoRow}>
224
+ {amount && (
225
+ <View style={styles.infoItem}>
226
+ {amountIconComponent || defaultAmountIcon}
227
+ <Text style={styles.amountText}>
228
+ {amount} {currency}
229
+ </Text>
230
+ </View>
231
+ )}
232
+ {expiry && (
233
+ <View style={styles.infoItem}>
234
+ {expiryIconComponent || defaultExpiryIcon}
235
+ <Text style={styles.expiryText}>{expiry}</Text>
236
+ </View>
237
+ )}
238
+ </View>
239
+
240
+ <View style={styles.codeBox}>
241
+ <Text style={styles.codeReadyText}>{codeReadyText}</Text>
242
+ <View style={styles.qrContainer}>
243
+ {tab === "qr" ? (
244
+ <QRCode value={code} size={qrCodeSize} />
245
+ ) : renderBarcodeComponent ? (
246
+ renderBarcodeComponent(code)
247
+ ) : (
248
+ <View style={styles.barcodePlaceholder}>
249
+ <Text style={styles.barcodePlaceholderText}>Bar Code</Text>
250
+ </View>
251
+ )}
252
+ </View>
253
+
254
+ {allowBarcodeSwitch && (
255
+ <View style={styles.tabRow}>
256
+ <TouchableOpacity
257
+ style={[
258
+ styles.tabButton,
259
+ tab !== "qr" && {
260
+ borderColor: finalInactiveTabBorderColor,
261
+ borderWidth: 1.5,
262
+ },
263
+ ]}
264
+ onPress={() => setTab("qr")}
265
+ >
266
+ <LinearGradient
267
+ colors={
268
+ tab === "qr"
269
+ ? (activeTabColors as any)
270
+ : [inactiveTabBackgroundColor, inactiveTabBackgroundColor]
271
+ }
272
+ start={tabGradientStart}
273
+ end={tabGradientEnd}
274
+ style={styles.tabGradient}
275
+ >
276
+ <Text
277
+ style={[
278
+ styles.tabTextBase,
279
+ tab === "qr"
280
+ ? styles.tabTextActive
281
+ : { color: finalInactiveTabTextColor },
282
+ ]}
283
+ >
284
+ {qrCodeLabel}
285
+ </Text>
286
+ </LinearGradient>
287
+ </TouchableOpacity>
288
+
289
+ <TouchableOpacity
290
+ style={[
291
+ styles.tabButton,
292
+ tab !== "bar" && {
293
+ borderColor: finalInactiveTabBorderColor,
294
+ borderWidth: 1.5,
295
+ },
296
+ ]}
297
+ onPress={() => setTab("bar")}
298
+ >
299
+ <LinearGradient
300
+ colors={
301
+ tab === "bar"
302
+ ? (activeTabColors as any)
303
+ : [inactiveTabBackgroundColor, inactiveTabBackgroundColor]
304
+ }
305
+ start={{ x: 0, y: 0.5 }}
306
+ end={{ x: 1, y: 0.5 }}
307
+ style={styles.tabGradient}
308
+ >
309
+ <Text
310
+ style={[
311
+ styles.tabTextBase,
312
+ tab === "bar"
313
+ ? styles.tabTextActive
314
+ : { color: finalInactiveTabTextColor },
315
+ ]}
316
+ >
317
+ {barCodeLabel}
318
+ </Text>
319
+ </LinearGradient>
320
+ </TouchableOpacity>
321
+ </View>
322
+ )}
323
+
324
+ <View style={styles.codeDisplayRow}>
325
+ <Text style={styles.actualCodeText}>{code}</Text>
326
+ {onCopyCode && (
327
+ <TouchableOpacity
328
+ onPress={handleCopyCode}
329
+ style={styles.copyButton}
330
+ >
331
+ {renderCopyIcon ? renderCopyIcon() : defaultCopyIcon}
332
+ </TouchableOpacity>
333
+ )}
334
+ </View>
335
+
336
+ {showAppleWalletButton && appleWalletIconSource && (
337
+ <Pressable
338
+ style={styles.walletButton}
339
+ onPress={onAppleWalletButtonPress}
340
+ >
341
+ <Image source={appleWalletIconSource} style={styles.walletIcon} />
342
+ <Text style={styles.walletText}>{appleWalletButtonText}</Text>
343
+ </Pressable>
344
+ )}
345
+ </View>
346
+
347
+ {onMyVouchersButtonPress && (
348
+ <TouchableOpacity
349
+ style={styles.vouchersButton}
350
+ onPress={onMyVouchersButtonPress}
351
+ >
352
+ <LinearGradient
353
+ colors={primaryButtonColors as any}
354
+ start={primaryButtonGradientStart}
355
+ end={primaryButtonGradientEnd}
356
+ style={styles.vouchersGradient}
357
+ >
358
+ <Text style={styles.vouchersText}>{myVouchersButtonText}</Text>
359
+ </LinearGradient>
360
+ </TouchableOpacity>
361
+ )}
362
+ </BottomSheetView>
363
+ </BottomSheet>
364
+ );
365
+ };
366
+
367
+ const getStyles = (theme: ThemeType) =>
368
+ StyleSheet.create({
369
+ sheetBackgroundBase: {
370
+ backgroundColor: theme.surface || "#fff",
371
+ borderTopLeftRadius: 24,
372
+ borderTopRightRadius: 24,
373
+ },
374
+ handleBase: {
375
+ backgroundColor: theme.border || "#e0e0e0",
376
+ width: 40,
377
+ height: 5,
378
+ borderRadius: 2.5,
379
+ alignSelf: "center",
380
+ marginTop: 8,
381
+ },
382
+ container: {
383
+ flex: 1,
384
+ alignItems: "center",
385
+ paddingHorizontal: 20,
386
+ paddingTop: 8,
387
+ paddingBottom: 20,
388
+ },
389
+ giftImage: {
390
+ width: 64,
391
+ height: 64,
392
+ marginBottom: 10,
393
+ resizeMode: "contain",
394
+ },
395
+ title: {
396
+ fontSize: 20,
397
+ fontWeight: "600",
398
+ marginBottom: 16,
399
+ color: theme.onSurface || "#333333",
400
+ },
401
+ infoRow: {
402
+ flexDirection: "row",
403
+ justifyContent: "space-around",
404
+ width: "100%",
405
+ marginBottom: 20,
406
+ },
407
+ infoItem: {
408
+ flexDirection: "row",
409
+ alignItems: "center",
410
+ },
411
+ defaultIconStyle: {
412
+ marginRight: 8,
413
+ },
414
+ amountText: {
415
+ fontSize: 16,
416
+ color: theme.onSurface || "#333333",
417
+ fontWeight: "500",
418
+ },
419
+ expiryText: {
420
+ fontSize: 16,
421
+ color: theme.onSurface || "#333333",
422
+ fontWeight: "500",
423
+ },
424
+ codeBox: {
425
+ backgroundColor: theme.surface || "#f8f8f8",
426
+ borderRadius: 18,
427
+ padding: 20,
428
+ width: "100%",
429
+ alignItems: "center",
430
+ marginBottom: 20,
431
+ shadowColor: "#000",
432
+ shadowOpacity: 0.08,
433
+ shadowRadius: 12,
434
+ shadowOffset: { width: 0, height: 4 },
435
+ elevation: 3,
436
+ },
437
+ codeReadyText: {
438
+ fontSize: 15,
439
+ color: theme.onSurface || "#666666",
440
+ marginBottom: 12,
441
+ },
442
+ qrContainer: {
443
+ marginBottom: 18,
444
+ alignItems: "center",
445
+ justifyContent: "center",
446
+ height: 130,
447
+ },
448
+ barcodePlaceholder: {
449
+ width: 150,
450
+ height: 70,
451
+ backgroundColor: theme.disabled || "#eeeeee",
452
+ alignItems: "center",
453
+ justifyContent: "center",
454
+ borderRadius: 8,
455
+ },
456
+ barcodePlaceholderText: {
457
+ color: theme.disabled || "#aaaaaa",
458
+ fontSize: 14,
459
+ },
460
+ tabRow: {
461
+ flexDirection: "row",
462
+ marginBottom: 16,
463
+ width: "100%",
464
+ justifyContent: "center",
465
+ },
466
+ tabButton: {
467
+ flex: 1,
468
+ marginHorizontal: 5,
469
+ borderRadius: 10,
470
+ overflow: "hidden",
471
+ },
472
+ tabGradient: {
473
+ paddingVertical: 10,
474
+ alignItems: "center",
475
+ borderRadius: 10,
476
+ },
477
+ tabTextBase: {
478
+ fontSize: 15,
479
+ fontWeight: "600",
480
+ },
481
+ tabTextActive: {
482
+ color: theme.onPrimary || "#fff", // Color for text on active tab gradient
483
+ fontWeight: "700",
484
+ },
485
+ codeDisplayRow: {
486
+ flexDirection: "row",
487
+ alignItems: "center",
488
+ justifyContent: "center",
489
+ marginVertical: 12,
490
+ paddingHorizontal: 10,
491
+ paddingVertical: 6,
492
+ backgroundColor: theme.background || "#f0f0f0", // Subtle background
493
+ borderRadius: 8,
494
+ },
495
+ actualCodeText: {
496
+ fontSize: 16,
497
+ letterSpacing: 1.5,
498
+ color: theme.onBackground || "#444444",
499
+ fontWeight: "500",
500
+ marginRight: 10,
501
+ },
502
+ copyButton: {
503
+ padding: 6,
504
+ },
505
+ copyIconText: { // Base style for copy icon, color applied dynamically
506
+ fontSize: 20,
507
+ },
508
+ walletButton: {
509
+ flexDirection: "row",
510
+ alignItems: "center",
511
+ backgroundColor: "#000", // Apple Wallet button is typically black
512
+ borderRadius: 10,
513
+ paddingVertical: 10,
514
+ paddingHorizontal: 20,
515
+ marginTop: 10,
516
+ },
517
+ walletIcon: {
518
+ width: 30,
519
+ height: 20,
520
+ marginRight: 10,
521
+ resizeMode: "contain",
522
+ },
523
+ walletText: {
524
+ color: "#fff", // Text on black button
525
+ fontWeight: "600",
526
+ fontSize: 15,
527
+ },
528
+ vouchersButton: {
529
+ width: "100%",
530
+ // marginTop: "auto",
531
+ marginTop: 20,
532
+ borderRadius: 12,
533
+ overflow: "hidden",
534
+ },
535
+ vouchersGradient: {
536
+ paddingVertical: 16,
537
+ alignItems: "center",
538
+ borderRadius: 12,
539
+ },
540
+ vouchersText: {
541
+ color: theme.onPrimary || "#fff", // Text on primary button gradient
542
+ fontWeight: "700",
543
+ fontSize: 17,
544
+ },
545
+ });
546
+
547
+ export default RedeemedVoucherSheet;