import React, { useCallback, useMemo, useRef } from "react"; import { View, Text, StyleSheet, TouchableOpacity, Pressable, ImageSourcePropType, StyleProp, ViewStyle, } from "react-native"; import { Image } from 'expo-image'; import BottomSheet, { BottomSheetView, BottomSheetProps, BottomSheetBackdrop, BottomSheetBackdropProps, } from "@gorhom/bottom-sheet"; import QRCode from "react-native-qrcode-svg"; import { LinearGradient } from "expo-linear-gradient"; import * as Clipboard from "expo-clipboard"; import { ThemeType, useTheme } from "../../theme"; import { Ionicons } from "@expo/vector-icons"; type Props = { visible: boolean; onClose: () => void; code: string; amount?: number; expiry?: string; image?: ImageSourcePropType; title?: string; currency?: string; codeReadyText?: string; qrCodeLabel?: string; barCodeLabel?: string; myVouchersButtonText?: string; onMyVouchersButtonPress?: () => void; onCopyCode?: (copiedCode: string) => void; showAppleWalletButton?: boolean; appleWalletButtonText?: string; onAppleWalletButtonPress?: () => void; appleWalletIconSource?: ImageSourcePropType; qrCodeSize?: number; activeTabColors?: string[]; inactiveTabBackgroundColor?: string; inactiveTabBorderColor?: string; inactiveTabTextColor?: string; primaryButtonColors?: string[]; allowBarcodeSwitch?: boolean; renderBarcodeComponent?: (code: string) => React.ReactNode; copyIconComponent?: React.ReactNode; amountIconComponent?: React.ReactNode; expiryIconComponent?: React.ReactNode; snapPoints?: string[]; sheetBackgroundStyle?: StyleProp; sheetHandleStyle?: StyleProp; backdropPressBehavior?: "close" | "none" | number; bottomSheetOverrideProps?: Partial< Omit< BottomSheetProps, | "children" | "snapPoints" | "index" | "onClose" | "enablePanDownToClose" | "backgroundStyle" | "handleIndicatorStyle" | "backdropComponent" > >; tabGradientStart?: { x: number; y: number }; tabGradientEnd?: { x: number; y: number }; primaryButtonGradientStart?: { x: number; y: number }; primaryButtonGradientEnd?: { x: number; y: number }; }; const RedeemedVoucherSheet: React.FC = (props) => { const { theme } = useTheme(); const styles = useMemo(() => getStyles(theme), [theme]); const defaultActiveTabColors = useMemo( () => theme.primary ? [theme.primary, theme.primaryVariant || theme.primary] : ["#F97794", "#623AA2"], [theme], ); const defaultPrimaryButtonColors = useMemo( () => defaultActiveTabColors, [theme, defaultActiveTabColors], ); const defaultInactiveTabBorderColor = useMemo( () => theme.primary || defaultActiveTabColors[1] || "#623AA2", [theme, defaultActiveTabColors], ); const defaultInactiveTabTextColor = useMemo( () => theme.primary || defaultActiveTabColors[1] || "#623AA2", [theme, defaultActiveTabColors], ); const { visible, onClose, code, amount, expiry, image, // Now directly from props title = "Successfully Redeemed!", currency = "SAR", codeReadyText = "Your Code Is Ready!", qrCodeLabel = "QR Code", barCodeLabel = "Bar Code", myVouchersButtonText = "My Vouchers", onMyVouchersButtonPress, onCopyCode, showAppleWalletButton = true, appleWalletButtonText = "Add to Apple Wallet", onAppleWalletButtonPress, appleWalletIconSource, // Now directly from props qrCodeSize = 120, activeTabColors = defaultActiveTabColors, inactiveTabBackgroundColor = theme.surface || "#FFFFFF", inactiveTabBorderColor: propInactiveTabBorderColor, inactiveTabTextColor: propInactiveTabTextColor, primaryButtonColors = defaultPrimaryButtonColors, allowBarcodeSwitch = true, renderBarcodeComponent, copyIconComponent, amountIconComponent, expiryIconComponent, snapPoints: propSnapPoints, sheetBackgroundStyle, sheetHandleStyle, backdropPressBehavior = "close", bottomSheetOverrideProps, tabGradientStart = { x: 0, y: 0.5 }, tabGradientEnd = { x: 1, y: 0.5 }, primaryButtonGradientStart = { x: 0, y: 0.5 }, primaryButtonGradientEnd = { x: 1, y: 0.5 }, } = props; const finalInactiveTabBorderColor = propInactiveTabBorderColor || defaultInactiveTabBorderColor; const finalInactiveTabTextColor = propInactiveTabTextColor || defaultInactiveTabTextColor; const bottomSheetRef = useRef(null); const finalSnapPoints = useMemo( () => propSnapPoints || ["75%"], [propSnapPoints], ); const [tab, setTab] = React.useState<"qr" | "bar">("qr"); const handleCopyCode = async () => { await Clipboard.setStringAsync(code); if (onCopyCode) { onCopyCode(code); } }; const closeBottomSheet = useCallback( () => { bottomSheetRef.current?.close(); }, [ /* onClose */ ] ); // Custom backdrop component const renderBackdrop = useCallback( (backdropProps: BottomSheetBackdropProps) => ( ), [backdropPressBehavior, theme], ); const iconSize = 24; const defaultAmountIcon = ( ); const defaultExpiryIcon = ( ); const defaultCopyIcon = ( ); return ( {image && ( )} {title} {amount && ( {amountIconComponent || defaultAmountIcon} {amount} {currency} )} {expiry && ( {expiryIconComponent || defaultExpiryIcon} {expiry} )} {codeReadyText} {tab === "qr" ? ( ) : renderBarcodeComponent ? ( renderBarcodeComponent(code) ) : ( Bar Code )} {allowBarcodeSwitch && ( setTab("qr")} > {qrCodeLabel} setTab("bar")} > {barCodeLabel} )} {code} {copyIconComponent || defaultCopyIcon} {showAppleWalletButton && appleWalletIconSource && ( {appleWalletButtonText} )} {onMyVouchersButtonPress && ( { closeBottomSheet(); onMyVouchersButtonPress() }} > {myVouchersButtonText} )} ); }; const getStyles = (theme: ThemeType) => StyleSheet.create({ sheetBackgroundBase: { backgroundColor: theme.surface || "#fff", borderTopLeftRadius: 24, borderTopRightRadius: 24, }, handleBase: { backgroundColor: theme.border || "#e0e0e0", width: 40, height: 5, borderRadius: 2.5, alignSelf: "center", marginTop: 8, }, container: { flex: 1, alignItems: "center", paddingHorizontal: 20, paddingTop: 8, paddingBottom: 20, }, giftImage: { width: 108, height: 84, marginBottom: 10, resizeMode: "contain", }, title: { fontSize: 20, fontWeight: "600", marginBottom: 16, color: theme.onSurface || "#333333", }, infoRow: { flexDirection: "row", justifyContent: "space-around", width: "100%", marginBottom: 20, }, infoItem: { flexDirection: "row", alignItems: "center", }, defaultIconStyle: { marginRight: 8, }, amountText: { fontSize: 16, color: theme.onSurface || "#333333", fontWeight: "500", }, expiryText: { fontSize: 16, color: theme.onSurface || "#333333", fontWeight: "500", }, codeBox: { backgroundColor: theme.surface || "#f8f8f8", borderRadius: 18, padding: 20, width: "100%", alignItems: "center", marginBottom: 20, shadowColor: "#000", shadowOpacity: 0.08, shadowRadius: 12, shadowOffset: { width: 0, height: 4 }, elevation: 3, }, codeReadyText: { fontSize: 15, color: theme.onSurface || "#666666", marginBottom: 12, }, qrContainer: { marginBottom: 18, alignItems: "center", justifyContent: "center", height: 130, }, barcodePlaceholder: { width: 150, height: 70, backgroundColor: theme.disabled || "#eeeeee", alignItems: "center", justifyContent: "center", borderRadius: 8, }, barcodePlaceholderText: { color: theme.disabled || "#aaaaaa", fontSize: 14, }, tabRow: { flexDirection: "row", marginBottom: 16, width: "100%", justifyContent: "center", }, tabButton: { flex: 1, marginHorizontal: 5, borderRadius: 10, overflow: "hidden", }, tabGradient: { paddingVertical: 10, alignItems: "center", borderRadius: 10, }, tabTextBase: { fontSize: 15, fontWeight: "600", }, tabTextActive: { color: theme.onPrimary || "#fff", // Color for text on active tab gradient fontWeight: "700", }, codeDisplayRow: { flexDirection: "row", alignItems: "center", justifyContent: "center", marginVertical: 12, paddingHorizontal: 10, paddingVertical: 6, // backgroundColor: theme.background || "#f0f0f0", // Subtle background borderRadius: 8, }, actualCodeText: { fontSize: 16, letterSpacing: 1.5, color: theme.onBackground || "#444444", fontWeight: "500", marginRight: 10, }, copyButton: { padding: 6, }, copyIconText: { // Base style for copy icon, color applied dynamically fontSize: 20, }, walletButton: { flexDirection: "row", alignItems: "center", backgroundColor: "#000", // Apple Wallet button is typically black borderRadius: 10, paddingVertical: 10, paddingHorizontal: 20, marginTop: 10, }, walletIcon: { width: 30, height: 20, marginRight: 10, resizeMode: "contain", }, walletText: { color: "#fff", // Text on black button fontWeight: "600", fontSize: 15, }, vouchersButton: { width: "100%", // marginTop: "auto", marginTop: 20, borderRadius: 12, overflow: "hidden", }, vouchersGradient: { paddingVertical: 16, alignItems: "center", borderRadius: 12, }, vouchersText: { color: theme.onPrimary || "#fff", // Text on primary button gradient fontWeight: "700", fontSize: 17, }, }); export default RedeemedVoucherSheet;