UNPKG

@churchapps/apphelper-donations

Version:
188 lines 12.9 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useCallback, useState, useEffect } from "react"; import { InputBox, ErrorMessages } from "@churchapps/apphelper"; import { FundDonations } from "."; import { DonationPreviewModal } from "../modals/DonationPreviewModal"; import { ApiHelper, CurrencyHelper, DateHelper } from "@churchapps/helpers"; import { Locale } from "../helpers"; import { Grid, InputLabel, MenuItem, Select, TextField, FormControl, Button, FormControlLabel, Checkbox, FormGroup, Typography } from "@mui/material"; import { DonationHelper } from "../helpers"; export const DonationForm = (props) => { const [errorMessage, setErrorMessage] = useState(); const [fundDonations, setFundDonations] = useState(); const [funds, setFunds] = useState([]); const [fundsTotal, setFundsTotal] = useState(0); const [transactionFee, setTransactionFee] = useState(0); const [payFee, setPayFee] = useState(0); const [total, setTotal] = useState(0); const [paymentMethodName, setPaymentMethodName] = useState(props?.paymentMethods?.length > 0 ? `${props.paymentMethods[0].name} ****${props.paymentMethods[0].last4}` : ""); const [donationType, setDonationType] = useState(); const [showDonationPreviewModal, setShowDonationPreviewModal] = useState(false); const [interval, setInterval] = useState("one_month"); const [gateway, setGateway] = useState(null); const [donation, setDonation] = useState({ id: props?.paymentMethods?.length > 0 ? props.paymentMethods[0].id : "", type: props?.paymentMethods?.length > 0 ? props.paymentMethods[0].type : "", customerId: props.customerId, person: { id: props.person?.id, email: props.person?.contactInfo?.email, name: props.person?.name?.display }, amount: 0, billing_cycle_anchor: +new Date(), interval: { interval_count: 1, interval: "month" }, funds: [] }); const loadData = useCallback(() => { ApiHelper.get("/funds", "GivingApi").then((data) => { setFunds(data); if (data.length) setFundDonations([{ fundId: data[0].id }]); }); ApiHelper.get("/gateways", "GivingApi").then((data) => { if (data.length !== 0) setGateway(data[0]); }); }, []); const handleSave = useCallback(() => { if (donation.amount < .5) setErrorMessage(Locale.label("donation.donationForm.tooLow")); else setShowDonationPreviewModal(true); }, [donation.amount]); const handleKeyDown = useCallback((e) => { if (e.key === "Enter") { e.preventDefault(); handleSave(); } }, [handleSave]); const handleCheckChange = useCallback((e, checked) => { const d = { ...donation }; d.amount = checked ? fundsTotal + transactionFee : fundsTotal; const showFee = checked ? transactionFee : 0; setTotal(d.amount); setPayFee(showFee); setDonation(d); }, [donation, fundsTotal, transactionFee]); const handleChange = useCallback((e) => { setErrorMessage(null); const d = { ...donation }; const value = e.target.value; switch (e.target.name) { case "method": d.id = value; const pm = props.paymentMethods.find(pm => pm.id === value); d.type = pm.type; setPaymentMethodName(`${pm.name} ****${pm.last4}`); break; case "type": setDonationType(value); break; case "date": d.billing_cycle_anchor = +new Date(value); break; case "interval": setInterval(value); d.interval = DonationHelper.getInterval(value); break; case "notes": d.notes = value; break; case "transaction-fee": const element = e.target; d.amount = element.checked ? fundsTotal + transactionFee : fundsTotal; const showFee = element.checked ? transactionFee : 0; setTotal(d.amount); setPayFee(showFee); } setDonation(d); }, [donation, props.paymentMethods, fundsTotal, transactionFee]); const handleCancel = useCallback(() => { setDonationType(null); }, []); const handleDonationSelect = useCallback((type) => { const dt = donationType === type ? null : type; setDonationType(dt); }, [donationType]); const handleSingleDonationClick = useCallback(() => handleDonationSelect("once"), [handleDonationSelect]); const handleRecurringDonationClick = useCallback(() => handleDonationSelect("recurring"), [handleDonationSelect]); const makeDonation = useCallback(async (message) => { let results; const churchObj = { name: props?.church?.name, subDomain: props?.church?.subDomain, churchURL: typeof window !== "undefined" && window.location.origin, logo: props?.churchLogo }; if (donationType === "once") results = await ApiHelper.post("/donate/charge/", { ...donation, church: churchObj }, "GivingApi"); if (donationType === "recurring") results = await ApiHelper.post("/donate/subscribe/", { ...donation, church: churchObj }, "GivingApi"); if (results?.status === "succeeded" || results?.status === "pending" || results?.status === "active") { setShowDonationPreviewModal(false); setDonationType(null); props.donationSuccess(message); } if (results?.raw?.message) { setShowDonationPreviewModal(false); setErrorMessage(Locale.label("donation.common.error") + ": " + results?.raw?.message); } }, [donation, donationType, props.church?.name, props.church?.subDomain, props.churchLogo, props.donationSuccess]); const handleFundDonationsChange = useCallback(async (fd) => { setErrorMessage(null); setFundDonations(fd); let totalAmount = 0; const selectedFunds = []; for (const fundDonation of fd) { totalAmount += fundDonation.amount || 0; const fund = funds.find((fund) => fund.id === fundDonation.fundId); selectedFunds.push({ id: fundDonation.fundId, amount: fundDonation.amount || 0, name: fund.name }); } const d = { ...donation }; d.amount = totalAmount; d.funds = selectedFunds; setFundsTotal(totalAmount); const fee = await getTransactionFee(totalAmount); setTransactionFee(fee); if (gateway && gateway.payFees === true) { d.amount = totalAmount + fee; setPayFee(fee); } setTotal(d.amount); setDonation(d); }, [donation, funds, gateway]); const getTransactionFee = useCallback(async (amount) => { if (amount > 0) { let dt = ""; if (donation.type === "card") dt = "creditCard"; if (donation.type === "bank") dt = "ach"; try { const response = await ApiHelper.post("/donate/fee?churchId=" + props?.church?.id, { type: dt, amount }, "GivingApi"); return response.calculatedFee; } catch (error) { console.log("Error calculating transaction fee: ", error); return 0; } } else { return 0; } }, [donation.type, props?.church?.id]); useEffect(() => { loadData(); }, [loadData, props.person?.id]); if (!funds.length || !props?.paymentMethods?.length) return null; else { return (_jsxs(_Fragment, { children: [_jsx(DonationPreviewModal, { show: showDonationPreviewModal, onHide: () => setShowDonationPreviewModal(false), handleDonate: makeDonation, donation: donation, donationType: donationType, payFee: payFee, paymentMethodName: paymentMethodName, funds: funds }), _jsxs(InputBox, { id: "donation-form", "aria-label": "donation-box", headerIcon: "volunteer_activism", headerText: Locale.label("donation.donationForm.donate"), ariaLabelSave: "save-button", cancelFunction: donationType ? handleCancel : undefined, saveFunction: donationType ? handleSave : undefined, saveText: Locale.label("donation.donationForm.preview"), children: [_jsxs(Grid, { id: "donation-type-selector", container: true, spacing: 3, children: [_jsx(Grid, { size: { xs: 12, md: 6 }, children: _jsx(Button, { id: "single-donation-button", "aria-label": "single-donation", size: "small", fullWidth: true, style: { minHeight: "50px" }, variant: donationType === "once" ? "contained" : "outlined", onClick: handleSingleDonationClick, children: Locale.label("donation.donationForm.make") }) }), _jsx(Grid, { size: { xs: 12, md: 6 }, children: _jsx(Button, { id: "recurring-donation-button", "aria-label": "recurring-donation", size: "small", fullWidth: true, style: { minHeight: "50px" }, variant: donationType === "recurring" ? "contained" : "outlined", onClick: handleRecurringDonationClick, children: Locale.label("donation.donationForm.makeRecurring") }) })] }), donationType && _jsxs("div", { id: "donation-details", style: { marginTop: "20px" }, children: [_jsx(Grid, { container: true, spacing: 3, children: _jsx(Grid, { size: 12, children: _jsxs(FormControl, { fullWidth: true, children: [_jsx(InputLabel, { children: Locale.label("donation.donationForm.method") }), _jsx(Select, { id: "payment-method-select", label: Locale.label("donation.donationForm.method"), name: "method", "aria-label": "method", value: donation.id, className: "capitalize", onChange: handleChange, children: props.paymentMethods.map((paymentMethod, i) => _jsxs(MenuItem, { value: paymentMethod.id, children: [paymentMethod.name, " ****", paymentMethod.last4] }, i)) })] }) }) }), donationType === "recurring" && _jsxs(Grid, { container: true, spacing: 3, style: { marginTop: 10 }, children: [_jsx(Grid, { size: { xs: 12, md: 6 }, children: _jsx(TextField, { id: "start-date-field", fullWidth: true, name: "date", type: "date", "aria-label": "date", label: Locale.label("donation.donationForm.startDate"), value: DateHelper.formatHtml5Date(new Date(donation.billing_cycle_anchor)), onChange: handleChange, onKeyDown: handleKeyDown }) }), _jsx(Grid, { size: { xs: 12, md: 6 }, children: _jsxs(FormControl, { fullWidth: true, children: [_jsx(InputLabel, { children: Locale.label("donation.donationForm.frequency") }), _jsxs(Select, { id: "frequency-select", label: Locale.label("donation.donationForm.frequency"), name: "interval", "aria-label": "interval", value: interval, onChange: handleChange, children: [_jsx(MenuItem, { value: "one_week", children: Locale.label("donation.donationForm.weekly") }), _jsx(MenuItem, { value: "two_week", children: Locale.label("donation.donationForm.biWeekly") }), _jsx(MenuItem, { value: "one_month", children: Locale.label("donation.donationForm.monthly") }), _jsx(MenuItem, { value: "three_month", children: Locale.label("donation.donationForm.quarterly") }), _jsx(MenuItem, { value: "one_year", children: Locale.label("donation.donationForm.annually") })] })] }) })] }), _jsxs("div", { id: "fund-selection", className: "form-group", children: [funds && fundDonations && _jsxs(_Fragment, { children: [_jsx("h4", { children: Locale.label("donation.donationForm.fund") }), _jsx(FundDonations, { fundDonations: fundDonations, funds: funds, updatedFunction: handleFundDonationsChange })] }), fundsTotal > 0 && _jsxs(_Fragment, { children: [(gateway && gateway.payFees === true) ? _jsxs(Typography, { fontSize: 14, fontStyle: "italic", children: ["*", Locale.label("donation.donationForm.fees").replace("{}", CurrencyHelper.formatCurrency(transactionFee))] }) : (_jsx(FormGroup, { children: _jsx(FormControlLabel, { control: _jsx(Checkbox, {}), name: "transaction-fee", label: Locale.label("donation.donationForm.cover").replace("{}", CurrencyHelper.formatCurrency(transactionFee)), onChange: handleCheckChange }) })), _jsxs("p", { children: [Locale.label("donation.donationForm.total"), ": $", total] })] }), _jsx(TextField, { id: "donation-notes", fullWidth: true, label: Locale.label("donation.donationForm.notes"), multiline: true, "aria-label": "note", name: "notes", value: donation.notes || "", onChange: handleChange, onKeyDown: handleKeyDown })] }), errorMessage && _jsx(ErrorMessages, { errors: [errorMessage] })] })] })] })); } }; //# sourceMappingURL=DonationForm.js.map