import React, { useState, useEffect } from "react"; import { Modal, View, Text, Image, TouchableOpacity, ScrollView, Linking, } from "react-native"; import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; import { SafeAreaView } from "react-native-safe-area-context"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { X, Phone, Mail, User, MessageCircle } from "lucide-react-native"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import BottomSheet from "~/components/ui/bottomSheet"; import { Contact } from "~/lib/stores"; import { router } from "expo-router"; import { ROUTES } from "~/lib/routes"; import { useTranslation } from "react-i18next"; interface ContactModalProps { visible: boolean; contact: Contact | null; onClose: () => void; } type LinkedAccount = { id: string; bankId: string; bankName: string; accountNumber: string; }; const BANK_OPTIONS: { id: string; name: string }[] = [ { id: "cbe", name: "Commercial Bank of Ethiopia" }, { id: "dashen", name: "Dashen Bank" }, { id: "abay", name: "Abay Bank" }, { id: "awash", name: "Awash Bank" }, { id: "hibret", name: "Hibret Bank" }, { id: "telebirr", name: "Ethio Telecom (Telebirr)" }, { id: "safaricom", name: "Safaricom M-PESA" }, ]; export default function ContactModal({ visible, contact, onClose, }: ContactModalProps) { const { t } = useTranslation(); const [linkedAccounts, setLinkedAccounts] = useState([]); const [isAddingAccount, setIsAddingAccount] = useState(false); const [selectedBank, setSelectedBank] = useState(null); const [accountNumber, setAccountNumber] = useState(""); useEffect(() => { const loadLinkedAccounts = async () => { if (!visible || !contact?.id) { setLinkedAccounts([]); return; } try { const storageKey = `contact_linked_accounts_${contact.id}`; const stored = await AsyncStorage.getItem(storageKey); if (stored) { const parsed = JSON.parse(stored); if (Array.isArray(parsed)) { setLinkedAccounts(parsed as LinkedAccount[]); } else { setLinkedAccounts([]); } } else { setLinkedAccounts([]); } } catch (error) { if (__DEV__) { console.warn( "[ContactModal] Failed to load linked accounts from storage", error ); } setLinkedAccounts([]); } }; loadLinkedAccounts(); }, [visible, contact]); if (!contact) return null; const displayName = contact.name || t("components.contactmodal.unknownContact"); const initials = displayName .split(" ") .map((n) => n[0]) .join("") .toUpperCase() .substring(0, 2); const handleCall = (phoneNumber: string) => { const cleanNumber = phoneNumber.replace(/[^+\d]/g, ""); Linking.openURL(`tel:${cleanNumber}`); }; const handleSMS = (phoneNumber: string) => { const cleanNumber = phoneNumber.replace(/[^+\d]/g, ""); Linking.openURL(`sms:${cleanNumber}`); }; const handleEmail = (email: string) => { Linking.openURL(`mailto:${email}`); }; const handleSendMoney = () => { if (!contact) return; // Close modal first onClose(); // Navigate to send money with contact info router.push({ pathname: ROUTES.SEND_OR_REQUEST_MONEY, params: { selectedContactId: contact.id, selectedContactName: contact.name, selectedContactPhone: contact.phoneNumbers?.[0]?.number || "", }, }); }; const handleStartAddAccount = () => { setIsAddingAccount(true); }; const handleSelectBank = (bankId: string) => { setSelectedBank(bankId); }; const handleSaveAccount = async () => { if (!selectedBank || !accountNumber.trim()) { return; } const bank = BANK_OPTIONS.find((b) => b.id === selectedBank); if (!bank) return; if (!contact?.id) { return; } const newAccount: LinkedAccount = { id: `${selectedBank}-${Date.now()}`, bankId: selectedBank, bankName: bank.name, accountNumber: accountNumber.trim(), }; const updatedAccounts = [...linkedAccounts, newAccount]; setLinkedAccounts(updatedAccounts); try { const storageKey = `contact_linked_accounts_${contact.id}`; await AsyncStorage.setItem(storageKey, JSON.stringify(updatedAccounts)); } catch (error) { if (__DEV__) { console.warn( "[ContactModal] Failed to persist linked accounts to storage", error ); } } setAccountNumber(""); setSelectedBank(null); setIsAddingAccount(false); }; const isTelecomWallet = selectedBank === "telebirr" || selectedBank === "safaricom"; const accountLabel = isTelecomWallet ? "Phone Number" : "Account Number"; const accountPlaceholder = isTelecomWallet ? "Enter phone number" : "Enter account number"; return ( {/* Header */} {t("components.contactmodal.headerTitle")} {/* Contact Avatar & Name */} {contact.imageAvailable && contact.image ? ( ) : ( {initials} )} {displayName} {contact.firstName && contact.lastName && ( {contact.firstName} {contact.lastName} )} {/* Contact Information */} {/* Phone Numbers */} {contact.phoneNumbers && contact.phoneNumbers.length > 0 && ( {t("components.contactmodal.phoneNumbersTitle")} {contact.phoneNumbers.map((phone, index) => ( {/* Add horizontal spacer here */} {phone.number} {phone.label && ( {phone.label} )} {/* handleCall(phone.number)} className="p-2 bg-green-100 rounded-full" > handleSMS(phone.number)} className="p-2 bg-blue-100 rounded-full" > */} ))} )} {/* Linked Accounts */} {linkedAccounts.length > 0 && ( Linked Accounts {linkedAccounts.map((account) => ( {account.bankName} {account.accountNumber} ))} )} {/* Email Addresses */} {contact.emails && contact.emails.length > 0 && ( {t("components.contactmodal.emailAddressesTitle")} {contact.emails.map((email, index) => ( {email.email} {email.label && ( {email.label} )} {/* handleEmail(email.email)} className="p-2 bg-purple-100 rounded-full" > */} ))} )} {/* No additional info message */} {(!contact.phoneNumbers || contact.phoneNumbers.length === 0) && (!contact.emails || contact.emails.length === 0) && ( {t("components.contactmodal.noAdditionalInfo")} )} {/* Action Buttons */} {/* Add Account Bottom Sheet */} setIsAddingAccount(false)} maxHeightRatio={0.9} > Add Account Bank {BANK_OPTIONS.map((bank) => { const isSelected = selectedBank === bank.id; const initials = bank.name .split(" ") .map((part) => part[0]) .join("") .toUpperCase() .slice(0, 2); return ( handleSelectBank(bank.id)} className={`items-center justify-between px-3 py-4 mb-3 rounded-2xl border ${ isSelected ? "border-primary bg-primary/5" : "border-gray-200 bg-white" }`} style={{ width: "30%" }} > {initials} {bank.name} ); })} {accountLabel} setAccountNumber(text.replace(/[^0-9]/g, "")) } containerClassName="w-full mb-4" borderClassName="border-[#E5E7EB] bg-white rounded-[4px]" placeholderColor="#9CA3AF" textClassName="text-[#111827] text-sm" keyboardType="number-pad" /> ); }