import { useCallback, useMemo, useRef, useState } from "react"; import { ThemeType, useTheme } from "../../theme"; import { View, StyleSheet, Text, TouchableOpacity, StyleProp, ViewStyle, TextStyle, } from "react-native"; import Slider from "@react-native-community/slider"; import NumericStepper from "../NumericStepper/NumericStepper"; interface SelectAmountProps { isRTL?: boolean; pointsValue?: number; minValue?: number; maxValue?: number; step?: number; conversionRate?: number; pointsLabel?: string; currencyLabel?: string; buttonText?: string; title?: string; containerStyle?: StyleProp; titleStyle?: StyleProp; rowStyle?: StyleProp; labelStyle?: StyleProp; currencyValueTextStyle?: StyleProp; stepperButtonStyle?: StyleProp; stepperButtonTextStyle?: StyleProp; stepperValueTextStyle?: StyleProp; sliderContainerStyle?: StyleProp; actionButtonStyle?: StyleProp; actionButtonTextStyle?: StyleProp; onValueChange?: (value: number) => void; onClick?: (value: number) => void; } const SelectAmount: React.FC = ({ isRTL, conversionRate = 20, minValue = 1, maxValue = 1000, pointsValue = 1, step = 20, title, buttonText = "Redeem", currencyLabel = "SAR", pointsLabel = "points", rowStyle, labelStyle, titleStyle, containerStyle, actionButtonStyle, actionButtonTextStyle, sliderContainerStyle, stepperButtonStyle, stepperButtonTextStyle, stepperValueTextStyle, currencyValueTextStyle, onValueChange, onClick, }) => { const { theme, isRTL: rtl } = useTheme(); isRTL = isRTL || rtl; const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]); const sliding = useRef(false); const clampedInitialValue = Math.max( minValue, Math.min(maxValue, pointsValue) ); const [currentValue, setCurrentValue] = useState(clampedInitialValue); const currencyValue = useMemo(() => { return conversionRate > 0 ? Math.ceil(currentValue / conversionRate) : 0; }, [currentValue, conversionRate]); const handleValueChange = useCallback( (newValue: number) => { let clampedValue = Math.max(minValue, Math.min(maxValue, newValue)); if (clampedValue !== currentValue && sliding.current) { setCurrentValue(Math.round(clampedValue)); onValueChange?.(clampedValue); } }, [minValue, maxValue, step, currentValue] ); const handleIncrement = () => { setCurrentValue((prev) => prev + step); }; const handleDecrement = () => { setCurrentValue((prev) => prev - step); }; return ( {title && {title}} {pointsLabel} {currencyLabel} {currencyValue} (sliding.current = true)} onSlidingComplete={() => (sliding.current = false)} minimumTrackTintColor={theme.primary} maximumTrackTintColor={theme.primary} thumbTintColor={theme.primary} inverted={isRTL} style={sliderContainerStyle} /> onClick?.(currentValue)} > {buttonText} ); }; const themedStyles = (theme: ThemeType, isRTL: boolean) => StyleSheet.create({ mainContainer: { width: "100%", backgroundColor: theme.surface, padding: 16, }, row: { flexDirection: isRTL ? "row-reverse" : "row", justifyContent: "space-between", alignItems: "center", marginBottom: 12, }, title: { fontSize: 18, fontWeight: "bold", color: theme.onSurface, marginBottom: 16, textAlign: isRTL ? "right" : "left", }, label: { fontSize: 14, color: theme.onSurface, }, controlButton: { backgroundColor: theme.secondary, width: 36, height: 36, borderRadius: 18, justifyContent: "center", alignItems: "center", }, actionButton: { backgroundColor: theme.primary, paddingVertical: 12, paddingHorizontal: 20, borderRadius: 6, alignItems: "center", marginTop: 16, }, valueText: { fontSize: 16, color: theme.onSurface, minWidth: 50, textAlign: "center", marginHorizontal: 8, }, currencyValueText: { fontSize: 16, color: theme.primary, minWidth: 50, textAlign: "center", marginHorizontal: 8, }, actionButtonText: { color: theme.onPrimary, }, }); export default SelectAmount;