UNPKG

@open-tender/utils

Version:

A library of utils for use with Open Tender applications that utilize our cloud-based Order API.

172 lines (171 loc) 7.15 kB
import { __awaiter } from "tslib"; import { useMemo, useEffect, useRef, useState } from 'react'; import { makeFormErrors, makeNumeric, validateCreditCard } from '../utils'; export const useDonationsForm = (purchase, reset, setAlert, loading, error, success, customer, creditCards, includeRecaptcha, cardData, cardType, windowRef, kountSessionId, requireCardholderName = false) => { const submitRef = useRef(null); const inputRef = useRef(null); const recaptchaRef = useRef(null); const [amount, setAmount] = useState(''); const [email, setEmail] = useState(''); const [isNewCard, setIsNewCard] = useState(true); const [creditCard, setCreditCard] = useState(null); const [creditCardOptions, setCreditCardOptions] = useState([]); const [errors, setErrors] = useState({}); const [submitting, setSubmitting] = useState(false); const errMsg = errors.form && errors.form.includes('parameters') ? 'There are one or more errors below' : errors.form || null; const newCardErrors = useMemo(() => errors ? Object.entries(errors) .filter(([key]) => key !== 'form') .reduce((obj, [key, value]) => (Object.assign(Object.assign({}, obj), { [key]: value })), {}) : {}, [errors]); useEffect(() => { var _a, _b; if (loading === 'idle') { setSubmitting(false); setAlert({ type: 'close' }); if (error) { if (recaptchaRef.current) recaptchaRef.current.reset(); setErrors(makeFormErrors(error)); ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus) && ((_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.focus()); windowRef === null || windowRef === void 0 ? void 0 : windowRef.scrollTo(0, 0); } else if (success) { windowRef === null || windowRef === void 0 ? void 0 : windowRef.scrollTo(0, 0); } } }, [windowRef, loading, error, setAlert, success]); useEffect(() => { if ((creditCards === null || creditCards === void 0 ? void 0 : creditCards.length) && loading !== 'pending') { const options = creditCards.map(i => ({ name: `${i.card_type_name} ending in ${i.last4}`, value: i.customer_card_id })); setCreditCardOptions(options); const defaultCard = creditCards.length ? { customer_card_id: creditCards[0].customer_card_id } : null; setCreditCard(defaultCard); setIsNewCard(false); } }, [creditCards, loading]); useEffect(() => { setEmail((customer === null || customer === void 0 ? void 0 : customer.email) || ''); }, [customer === null || customer === void 0 ? void 0 : customer.email]); const handleAmount = (value) => { const cleanValue = makeNumeric(value); setAmount(cleanValue); }; const handleEmail = (value) => { setEmail(value); }; const handleCreditCard = (value) => { const customerCardId = parseInt(value); setCreditCard({ customer_card_id: customerCardId }); }; const purchaseWithCaptcha = (credit_card) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c; const alert = { type: 'working', args: { text: 'Submitting your contribution...' } }; const formData = { amount: amount, email: email, credit_card, token: '' }; if (kountSessionId) formData.kount_device_session_id = kountSessionId; if (includeRecaptcha) { try { const isEnterpriseRecaptcha = ((_a = recaptchaRef.current) === null || _a === void 0 ? void 0 : _a.props.size) === 'invisible'; const token = isEnterpriseRecaptcha ? yield ((_b = recaptchaRef.current) === null || _b === void 0 ? void 0 : _b.executeAsync()) : (_c = recaptchaRef.current) === null || _c === void 0 ? void 0 : _c.getValue(); if (!token) { setSubmitting(false); setErrors({ form: 'Please complete the recaptcha before submitting' }); windowRef === null || windowRef === void 0 ? void 0 : windowRef.scrollTo(0, 0); } else { setSubmitting(true); setAlert(alert); purchase(Object.assign(Object.assign({}, formData), { token })); } } catch (err) { setSubmitting(false); setErrors({ form: 'Please complete the recaptcha before submitting' }); windowRef === null || windowRef === void 0 ? void 0 : windowRef.scrollTo(0, 0); } } else { setSubmitting(true); setAlert(alert); purchase(formData); } }); const handleSubmit = (evt) => { var _a, _b, _c; evt === null || evt === void 0 ? void 0 : evt.preventDefault(); if (!amount || !email) { setErrors({ form: 'Both amount and email are required' }); ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus) && inputRef.current.focus(); windowRef === null || windowRef === void 0 ? void 0 : windowRef.scrollTo(0, 0); } else { if (isNewCard) { if (cardData && cardType) { const { card, errors: errs } = validateCreditCard(cardData, cardType, requireCardholderName); if (errs) { setErrors(Object.assign(Object.assign({}, errs), { form: 'There are one or more credit card errors below' })); setSubmitting(false); windowRef === null || windowRef === void 0 ? void 0 : windowRef.scrollTo(0, 0); } else { purchaseWithCaptcha(card); } } } else { if (creditCard) purchaseWithCaptcha(creditCard); } ((_b = submitRef.current) === null || _b === void 0 ? void 0 : _b.blur) && ((_c = submitRef.current) === null || _c === void 0 ? void 0 : _c.blur()); } }; const handleReset = () => { setErrors({}); setAmount(null); if (!customer) setEmail(null); if (!customer) setIsNewCard(true); setCreditCard(null); setCreditCardOptions([]); reset(); }; return { inputRef, submitRef, recaptchaRef, amount, handleAmount, email, handleEmail, errors, errMsg, newCardErrors, submitting, isNewCard, creditCard, creditCardOptions, handleCreditCard, handleSubmit, handleReset, setErrors }; };