Initial commit
This commit is contained in:
249
src/screens/wallet/paymentMethod/ui/ModalCard.tsx
Normal file
249
src/screens/wallet/paymentMethod/ui/ModalCard.tsx
Normal file
@@ -0,0 +1,249 @@
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import packetsApi from 'api/packets';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Animated,
|
||||
Dimensions,
|
||||
Linking,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Check from 'svg/Check';
|
||||
import Click from 'svg/Click';
|
||||
import Payme from 'svg/Payme';
|
||||
import { RootStackParamList } from 'types/types';
|
||||
import { PaymentStyle } from '../../payment/ui/style';
|
||||
|
||||
const { height } = Dimensions.get('window');
|
||||
|
||||
interface ModalCardViewProps {
|
||||
isVisible: boolean;
|
||||
setIsVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
selectedId: 'click' | 'payme' | null;
|
||||
packId: number;
|
||||
setSelectedId: React.Dispatch<React.SetStateAction<'click' | 'payme' | null>>;
|
||||
}
|
||||
|
||||
type NavigationProp = NativeStackNavigationProp<
|
||||
RootStackParamList,
|
||||
'PaymentMethod'
|
||||
>;
|
||||
|
||||
const ModalCard = ({
|
||||
isVisible,
|
||||
setIsVisible,
|
||||
packId,
|
||||
selectedId,
|
||||
setSelectedId,
|
||||
}: ModalCardViewProps) => {
|
||||
const slideAnim = useRef(new Animated.Value(height)).current;
|
||||
const [load, setLoad] = React.useState(false);
|
||||
const [pay, setPay] = useState<string>('');
|
||||
const { t } = useTranslation();
|
||||
|
||||
const openLink = async (url: string) => {
|
||||
try {
|
||||
const supported = await Linking.canOpenURL(url);
|
||||
if (supported) {
|
||||
await Linking.openURL(url);
|
||||
} else {
|
||||
// Agar app ocholmasa, default brauzerda ochishga urinadi
|
||||
await Linking.openURL(url);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Link xatolik:', err);
|
||||
// Xato bo‘lsa ham brauzer orqali ochishga urinish
|
||||
try {
|
||||
await Linking.openURL(url);
|
||||
} catch (err2) {
|
||||
console.error('Brauzer orqali ham ochilmadi:', err2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { mutate, isPending } = useMutation({
|
||||
mutationFn: ({ id, payType }: { id: number; payType: string }) =>
|
||||
packetsApi.payPackets(id, { payType }),
|
||||
onSuccess: res => {
|
||||
setIsVisible(false);
|
||||
const url = res.data.paymentUrl;
|
||||
openLink(url);
|
||||
},
|
||||
onError: err => {
|
||||
console.dir(err);
|
||||
},
|
||||
});
|
||||
|
||||
const openModal = () => {
|
||||
Animated.timing(slideAnim, {
|
||||
toValue: 0,
|
||||
duration: 100,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
Animated.timing(slideAnim, {
|
||||
toValue: height,
|
||||
duration: 200,
|
||||
useNativeDriver: true,
|
||||
}).start(() => {
|
||||
setIsVisible(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handlePayment = () => {
|
||||
mutate({ id: packId, payType: pay });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible) openModal();
|
||||
}, [isVisible]);
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
return (
|
||||
<View style={styles.overlay}>
|
||||
<TouchableWithoutFeedback onPress={closeModal}>
|
||||
<View style={styles.backdrop} />
|
||||
</TouchableWithoutFeedback>
|
||||
|
||||
<Animated.View
|
||||
style={[styles.sheet, { transform: [{ translateY: slideAnim }] }]}
|
||||
>
|
||||
<View style={styles.sheetContent}>
|
||||
{/* CLICK */}
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.paymentOption,
|
||||
{
|
||||
backgroundColor:
|
||||
selectedId === 'click' ? '#28A7E81A' : '#FFFFFF',
|
||||
},
|
||||
]}
|
||||
onPress={() => setSelectedId('click')}
|
||||
>
|
||||
<View style={PaymentStyle.paymentCard}>
|
||||
<Click width={80} height={80} />
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
PaymentStyle.select,
|
||||
{
|
||||
backgroundColor:
|
||||
selectedId === 'click' ? '#28A7E8' : '#FFFFFF',
|
||||
borderColor: selectedId === 'click' ? '#28A7E8' : '#383838',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{selectedId === 'click' && (
|
||||
<Check color="#fff" width={20} height={20} />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* PAYME */}
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.paymentOption,
|
||||
{ backgroundColor: '#FFFFFF', marginBottom: 50 },
|
||||
]}
|
||||
onPress={() => {
|
||||
setPay('PAYME'), setSelectedId('payme');
|
||||
}}
|
||||
>
|
||||
<View style={PaymentStyle.paymentCard}>
|
||||
<Payme width={80} height={80} />
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
PaymentStyle.select,
|
||||
{
|
||||
backgroundColor:
|
||||
selectedId === 'payme' ? '#28A7E8' : '#FFFFFF',
|
||||
borderColor: selectedId === 'payme' ? '#28A7E8' : '#383838',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{selectedId === 'payme' && (
|
||||
<Check color="#fff" width={20} height={20} />
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
PaymentStyle.modalBtn,
|
||||
{
|
||||
margin: 'auto',
|
||||
right: 0,
|
||||
bottom: -20,
|
||||
backgroundColor:
|
||||
load || selectedId === null ? '#88888840' : '#28A7E8',
|
||||
},
|
||||
]}
|
||||
onPress={handlePayment}
|
||||
disabled={load}
|
||||
>
|
||||
{load || isPending ? (
|
||||
<ActivityIndicator size="small" color="#fff" />
|
||||
) : (
|
||||
<Text
|
||||
style={[
|
||||
PaymentStyle.btnText,
|
||||
{
|
||||
color: load || selectedId === null ? '#000000b9' : '#FFFF',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{t("To'lash")}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Animated.View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
overlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
zIndex: 1000,
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
backdrop: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
||||
},
|
||||
sheet: {
|
||||
width: '100%',
|
||||
backgroundColor: '#F3FAFF',
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
padding: 20,
|
||||
paddingBottom: 30,
|
||||
},
|
||||
sheetContent: {
|
||||
gap: 10,
|
||||
},
|
||||
paymentOption: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
borderRadius: 10,
|
||||
paddingLeft: 20,
|
||||
paddingRight: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default ModalCard;
|
||||
Reference in New Issue
Block a user