231 lines
6.9 KiB
TypeScript

import React, { useCallback, useState } from 'react';
import {
View,
Text,
SafeAreaView,
FlatList,
TouchableOpacity,
Modal,
TextInput,
KeyboardAvoidingView,
Platform,
Pressable,
} from 'react-native';
// import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { Header } from '@components';
import { useAppTheme } from '@theme';
import { getStyles } from './walletScreen.styles';
import { WalletTransaction } from '@interfaces';
import { useAppDispatch, useAppSelector } from '@store';
import { getAllWalletTransactions, initializeWalletTopUpThunk } from './thunk';
import { useFocusEffect } from '@react-navigation/native';
import { getWalletBalanceThunk } from '../accountScreen';
import { useStripePayment } from '../checkoutPaymentScreen/hooks/useStripePayment';
import { useTopUp } from './hooks/useTopUp';
// import { addMoneyThunk } from './thunk'; // wire this up to your actual top-up API
const WalletScreen = () => {
const { colors } = useAppTheme();
const styles = getStyles(colors);
const dispatch = useAppDispatch();
const { walletTransactions } = useAppSelector(state => state.wallet);
const { wallet } = useAppSelector(state => state.account);
const [isModalVisible, setIsModalVisible] = useState(false);
const [amount, setAmount] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState('');
const { topUpCardPayment, isPaymentProcessing } = useTopUp();
useFocusEffect(
useCallback(() => {
dispatch(getAllWalletTransactions());
dispatch(getWalletBalanceThunk());
}, []),
);
const openModal = () => {
setAmount('');
setError('');
setIsModalVisible(true);
};
const closeModal = () => {
if (isSubmitting) return;
setIsModalVisible(false);
};
const handleAmountChange = (text: string) => {
// allow only digits and a single decimal point
const sanitized = text.replace(/[^0-9.]/g, '');
setAmount(sanitized);
if (error) setError('');
};
const handleTopUp = async () => {
const numericAmount = parseFloat(amount);
if (!amount || isNaN(numericAmount) || numericAmount <= 0) {
setError('Please enter a valid amount');
return;
}
try {
setIsSubmitting(true);
const payload = {
amount: numericAmount,
paymentMethod: 'CARD'
}
const response = await dispatch(initializeWalletTopUpThunk(payload)).unwrap();
const success = await topUpCardPayment(response);
setIsSubmitting(false);
setIsModalVisible(false);
setAmount('');
} catch (e) {
setIsSubmitting(false);
setError('Something went wrong. Please try again.');
}
};
const renderItem = ({ item }: { item: WalletTransaction }) => {
const isCredit = item.direction === 'IN';
return (
<View style={styles.transactionCard}>
<View
style={[
styles.iconContainer,
{
backgroundColor: isCredit ? '#DFF7E4' : '#FFE5E5',
},
]}
>
{/* <Icon
name={isCredit ? 'arrow-bottom-left' : 'arrow-top-right'}
size={22}
color={isCredit ? '#18A558' : '#F04438'}
/> */}
</View>
<View style={styles.transactionInfo}>
<Text style={styles.transactionTitle}>{item.type}</Text>
<Text style={styles.transactionRef}>{item.transactionReference}</Text>
<Text style={styles.transactionDate}>
{new Date(item.createdAt).toLocaleString()}
</Text>
</View>
<View style={styles.amountContainer}>
<Text
style={[
styles.amount,
{
color: isCredit ? '#18A558' : '#F04438',
},
]}
>
{isCredit ? '+' : '-'}{item.amount}
</Text>
<Text style={styles.balanceText}>Bal {item.balanceAfter}</Text>
</View>
</View>
);
};
return (
<KeyboardAvoidingView style={styles.container}>
<Header title="Wallet" />
<View style={styles.balanceCard}>
<Text style={styles.balanceLabel}>Available Balance</Text>
<Text style={styles.balance}>{wallet?.balance.toFixed(2)}</Text>
<TouchableOpacity style={styles.addMoneyButton} onPress={openModal}>
{/* <Icon name="plus" color="#FFF" size={20} /> */}
<Text style={styles.addMoneyText}>Add Money</Text>
</TouchableOpacity>
</View>
<Text style={styles.sectionTitle}>Recent Transactions</Text>
<FlatList
data={walletTransactions}
keyExtractor={item => item.id}
renderItem={renderItem}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.listContainer}
ListEmptyComponent={
<View style={styles.emptyContainer}>
{/* <Icon name="wallet-outline" size={70} color="#BDBDBD" /> */}
<Text style={styles.emptyText}>No Transactions Yet</Text>
</View>
}
/>
<Modal
visible={isModalVisible}
transparent
animationType="fade"
onRequestClose={closeModal}
>
<KeyboardAvoidingView
style={styles.modalOverlay}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
>
<Pressable style={styles.modalBackdrop} onPress={closeModal} />
<View style={styles.modalCard}>
<Text style={styles.modalTitle}>Add Money</Text>
<Text style={styles.modalSubtitle}>
Enter an amount to top up your wallet
</Text>
<View style={styles.amountInputWrapper}>
<Text style={styles.rupeeSymbol}></Text>
<TextInput
style={styles.amountInput}
keyboardType="decimal-pad"
placeholder="0.00"
placeholderTextColor="#B0B0B0"
value={amount}
onChangeText={handleAmountChange}
autoFocus
/>
</View>
{error ? <Text style={styles.modalError}>{error}</Text> : null}
<TouchableOpacity
style={[
styles.topUpButton,
isSubmitting && styles.topUpButtonDisabled,
]}
onPress={handleTopUp}
disabled={isSubmitting}
>
<Text style={styles.topUpButtonText}>
{isSubmitting ? 'Processing...' : 'Add Top Up'}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.modalCancelButton}
onPress={closeModal}
disabled={isSubmitting}
>
<Text style={styles.modalCancelText}>Cancel</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</Modal>
</KeyboardAvoidingView>
);
};
export default WalletScreen;