import React, { useState, useEffect } from "react";
import { ScrollView, View, TouchableOpacity, Keyboard } from "react-native";
import { LucideEye, EyeOff, Trash2, CreditCard } from "lucide-react-native";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Text } from "~/components/ui/text";
import { router, useLocalSearchParams } from "expo-router";
import { useAuthWithProfile } from "~/lib/hooks/useAuthWithProfile";
import { useUserWallet } from "~/lib/hooks/useUserWallet";
import { CreditCard as CreditCardType } from "~/lib/services/walletService";
import { useTabStore } from "~/lib/stores";
import { addCardSchema, validate } from "~/lib/utils/validationSchemas";
import BackButton from "~/components/ui/backButton";
import { ROUTES } from "~/lib/routes";
import ScreenWrapper from "~/components/ui/ScreenWrapper";
import ModalToast from "~/components/ui/toast";
import { useTranslation } from "react-i18next";
// Credit Card Component
const CreditCardComponent = ({
card,
onRemove,
}: {
card: CreditCardType;
onRemove: () => void;
}) => {
const getCardColor = (cardType: string) => {
switch (cardType?.toLowerCase()) {
case "visa":
return "bg-blue-700";
case "mastercard":
return "bg-red-600";
case "american express":
return "bg-green-700";
case "discover":
return "bg-orange-600";
default:
return "bg-gray-700";
}
};
const getCardIcon = (cardType: string) => {
switch (cardType?.toLowerCase()) {
case "visa":
return "VISA";
case "mastercard":
return "MC";
case "american express":
return "AMEX";
case "discover":
return "DISC";
default:
return "CARD";
}
};
return (
{/* Card Brand and Remove Button */}
{getCardIcon(card.cardType || "")}
{
console.log("Remove button pressed for card:", card.id);
onRemove();
}}
className="bg-gray-500/80 p-3 rounded-full min-w-10 min-h-10 flex items-center justify-center"
activeOpacity={0.7}
style={{ zIndex: 10 }}
>
{/* Card Number */}
{card.cardNumber}
{/* Card Details */}
Valid Thru
{card.expiryDate}
Card Type
{card.cardType || "Unknown"}
{/* Decorative Elements */}
);
};
export default function AddCard() {
const { user } = useAuthWithProfile();
const { addCreditCard, loading, error } = useUserWallet(user);
const { setLastVisitedTab } = useTabStore();
const { from } = useLocalSearchParams<{ from?: string }>();
const { t } = useTranslation();
const [toastVisible, setToastVisible] = useState(false);
const [toastTitle, setToastTitle] = useState("");
const [toastDescription, setToastDescription] = useState(
undefined
);
const [toastVariant, setToastVariant] = useState<
"success" | "error" | "warning" | "info"
>("info");
const toastTimeoutRef = React.useRef | null>(
null
);
const showToast = (
title: string,
description?: string,
variant: "success" | "error" | "warning" | "info" = "info"
) => {
if (toastTimeoutRef.current) {
clearTimeout(toastTimeoutRef.current);
}
setToastTitle(title);
setToastDescription(description);
setToastVariant(variant);
setToastVisible(true);
toastTimeoutRef.current = setTimeout(() => {
setToastVisible(false);
toastTimeoutRef.current = null;
}, 2500);
};
// Set the tab state when component mounts based on where user came from
useEffect(() => {
if (from === "addcash") {
setLastVisitedTab("/(tabs)/cardmang");
} else {
setLastVisitedTab("/"); // Default to home if no specific from parameter
}
}, [setLastVisitedTab, from]);
useEffect(() => {
return () => {
if (toastTimeoutRef.current) {
clearTimeout(toastTimeoutRef.current);
}
};
}, []);
// Form state
const [cardNumber, setCardNumber] = useState("");
const [expiryDate, setExpiryDate] = useState("");
const [cvv, setCvv] = useState("");
const [showCvv, setShowCvv] = useState(false);
// Format card number as user types (add spaces every 4 digits)
const formatCardNumber = (value: string) => {
const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
const matches = v.match(/\d{4,16}/g);
const match = (matches && matches[0]) || "";
const parts = [];
for (let i = 0, len = match.length; i < len; i += 4) {
parts.push(match.substring(i, i + 4));
}
if (parts.length) {
return parts.join(" ");
} else {
return v;
}
};
// Format expiry date as MM/YY
const formatExpiryDate = (value: string) => {
const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
if (v.length >= 2) {
return `${v.substring(0, 2)}/${v.substring(2, 4)}`;
}
return v;
};
const handleCardNumberChange = (value: string) => {
const formatted = formatCardNumber(value);
if (formatted.length <= 19) {
// 16 digits + 3 spaces
setCardNumber(formatted);
}
};
const handleExpiryDateChange = (value: string) => {
const formatted = formatExpiryDate(value);
if (formatted.length <= 5) {
// MM/YY
setExpiryDate(formatted);
}
};
const handleCvvChange = (value: string) => {
const v = value.replace(/[^0-9]/gi, "");
if (v.length <= 4) {
setCvv(v);
}
};
const handleAddCard = async () => {
Keyboard.dismiss();
// Basic field validation
if (!cardNumber.trim()) {
showToast(
t("addcard.validationErrorTitle"),
t("addcard.validationCardNumberRequired"),
"error"
);
return;
}
if (!expiryDate.trim()) {
showToast(
t("addcard.validationErrorTitle"),
t("addcard.validationExpiryRequired"),
"error"
);
return;
}
if (!cvv.trim()) {
showToast(
t("addcard.validationErrorTitle"),
t("addcard.validationCvvRequired"),
"error"
);
return;
}
// Validate form using valibot
const validationResult = validate(addCardSchema, {
cardNumber,
expiryDate,
cvv,
});
if (!validationResult.success) {
showToast(
t("addcard.validationErrorTitle"),
validationResult.error || t("addcard.validationInvalidCard"),
"error"
);
return;
}
try {
await addCreditCard({
cardNumber: validationResult.data.cardNumber.replace(/\s/g, ""), // Remove spaces
expiryDate: validationResult.data.expiryDate,
cvv: validationResult.data.cvv,
});
router.replace(ROUTES.CARD_ADDED);
} catch (err) {
showToast(
t("addcard.toastErrorTitle"),
t("addcard.toastAddFailed"),
"error"
);
}
};
// Show errors
useEffect(() => {
if (error) {
showToast(t("addcard.toastErrorTitle"), error, "error");
}
}, [error]);
return (
{t("addcard.title")}
{t("addcard.sectionCardTitle")}
{t("addcard.sectionCardSubtitle")}
setShowCvv(!showCvv)}>
{showCvv ? (
) : (
)}
}
/>
);
}