@churchapps/apphelper-donations
Version:
Donation components for ChurchApps AppHelper
118 lines • 5.73 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useCallback } from "react";
import { Grid, TextField, Box } from "@mui/material";
const validateCardNumber = (number) => {
// Remove spaces and non-numeric characters
const cleanNumber = number.replace(/\D/g, "");
// Check length (13-19 digits for most cards)
if (cleanNumber.length < 13 || cleanNumber.length > 19) {
return false;
}
// Luhn algorithm
let sum = 0;
let isEven = false;
for (let i = cleanNumber.length - 1; i >= 0; i--) {
let digit = parseInt(cleanNumber.charAt(i));
if (isEven) {
digit *= 2;
if (digit > 9) {
digit -= 9;
}
}
sum += digit;
isEven = !isEven;
}
return sum % 10 === 0;
};
const validateExpiryDate = (month, year) => {
const currentDate = new Date();
const currentMonth = currentDate.getMonth() + 1;
const currentYear = currentDate.getFullYear();
const expMonth = parseInt(month);
let expYear = parseInt(year);
// Support 2-digit year inputs by converting to full year (e.g., 25 => 2025)
if (!isNaN(expYear) && expYear < 100)
expYear = 2000 + expYear;
if (isNaN(expMonth) || expMonth < 1 || expMonth > 12)
return false;
if (isNaN(expYear))
return false;
if (expYear < currentYear)
return false;
if (expYear === currentYear && expMonth < currentMonth)
return false;
return true;
};
const validateCVV = (cvv) => {
return /^\d{3,4}$/.test(cvv);
};
export const PayPalCardForm = ({ onCardDataChange, style }) => {
const [cardNumber, setCardNumber] = useState("");
const [expiryMonth, setExpiryMonth] = useState("");
const [expiryYear, setExpiryYear] = useState("");
const [cvv, setCvv] = useState("");
const [holderName, setHolderName] = useState("");
const formatCardNumber = (value) => {
// Remove all non-numeric characters
const numericOnly = value.replace(/\D/g, "");
// Add spaces every 4 digits
const formatted = numericOnly.replace(/(\d{4})(?=\d)/g, "$1 ");
// Limit to 19 digits (including spaces)
return formatted.substring(0, 23);
};
const validateAndNotify = useCallback((cardNum, expMonth, expYear, cvvValue, name) => {
const errors = [];
const cleanCardNumber = cardNum.replace(/\D/g, "");
if (!name.trim()) {
errors.push("Card holder name is required");
}
if (!validateCardNumber(cleanCardNumber)) {
errors.push("Invalid card number");
}
if (!validateExpiryDate(expMonth, expYear)) {
errors.push("Invalid expiry date");
}
if (!validateCVV(cvvValue)) {
errors.push("Invalid CVV");
}
const cardData = {
cardNumber: cleanCardNumber,
expiryMonth: expMonth.padStart(2, "0"),
expiryYear: expYear,
cvv: cvvValue,
holderName: name,
isValid: errors.length === 0,
errors
};
onCardDataChange?.(cardData);
}, [onCardDataChange]);
const handleCardNumberChange = (e) => {
const formatted = formatCardNumber(e.target.value);
setCardNumber(formatted);
validateAndNotify(formatted, expiryMonth, expiryYear, cvv, holderName);
};
const handleExpiryMonthChange = (e) => {
const value = e.target.value.replace(/\D/g, "").substring(0, 2);
setExpiryMonth(value);
validateAndNotify(cardNumber, value, expiryYear, cvv, holderName);
};
const handleExpiryYearChange = (e) => {
const value = e.target.value.replace(/\D/g, "").substring(0, 4);
setExpiryYear(value);
validateAndNotify(cardNumber, expiryMonth, value, cvv, holderName);
};
const handleCvvChange = (e) => {
const value = e.target.value.replace(/\D/g, "").substring(0, 4);
setCvv(value);
validateAndNotify(cardNumber, expiryMonth, expiryYear, value, holderName);
};
const handleHolderNameChange = (e) => {
const value = e.target.value;
setHolderName(value);
validateAndNotify(cardNumber, expiryMonth, expiryYear, cvv, value);
};
// Note: years and months arrays could be used for dropdown selects if needed in the future
return (_jsx(Box, { style: { ...style }, sx: { p: 1.5, backgroundColor: "white", border: "1px solid #ccc", borderRadius: 1 }, children: _jsxs(Grid, { container: true, spacing: 2, children: [_jsx(Grid, { size: 12, children: _jsx(TextField, { fullWidth: true, label: "Card Holder Name", value: holderName, onChange: handleHolderNameChange, placeholder: "John Doe", size: "small" }) }), _jsx(Grid, { size: 12, children: _jsx(TextField, { fullWidth: true, label: "Card Number", value: cardNumber, onChange: handleCardNumberChange, placeholder: "1234 5678 9012 3456", inputProps: { maxLength: 23 }, size: "small" }) }), _jsx(Grid, { size: { xs: 6, sm: 3 }, children: _jsx(TextField, { fullWidth: true, label: "Month", value: expiryMonth, onChange: handleExpiryMonthChange, placeholder: "MM", inputProps: { maxLength: 2 }, size: "small" }) }), _jsx(Grid, { size: { xs: 6, sm: 3 }, children: _jsx(TextField, { fullWidth: true, label: "Year", value: expiryYear, onChange: handleExpiryYearChange, placeholder: "YYYY", inputProps: { maxLength: 4 }, size: "small" }) }), _jsx(Grid, { size: { xs: 12, sm: 6 }, children: _jsx(TextField, { fullWidth: true, label: "CVV", value: cvv, onChange: handleCvvChange, placeholder: "123", inputProps: { maxLength: 4 }, size: "small" }) })] }) }));
};
//# sourceMappingURL=PayPalCardForm.js.map