@churchapps/apphelper 0.4.6 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHUMS_COMPONENT_EXTRACTION_CANDIDATES.md +210 -0
  2. package/COMPONENT_USAGE_REPORT.md +322 -0
  3. package/dist/components/header/SecondaryMenu.js +3 -3
  4. package/dist/components/header/SecondaryMenu.js.map +1 -1
  5. package/dist/components/index.d.ts +0 -2
  6. package/dist/components/index.d.ts.map +1 -1
  7. package/dist/components/index.js +1 -5
  8. package/dist/components/index.js.map +1 -1
  9. package/dist/helpers/FileHelper.d.ts +1 -1
  10. package/dist/helpers/FileHelper.d.ts.map +1 -1
  11. package/dist/helpers/FileHelper.js +2 -6
  12. package/dist/helpers/FileHelper.js.map +1 -1
  13. package/dist/index.d.ts +0 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +0 -1
  16. package/dist/index.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/components/header/SecondaryMenu.tsx +3 -3
  19. package/src/components/index.tsx +0 -2
  20. package/src/helpers/FileHelper.ts +3 -6
  21. package/src/index.ts +0 -1
  22. package/dist/components/CreatePerson.d.ts +0 -15
  23. package/dist/components/CreatePerson.d.ts.map +0 -1
  24. package/dist/components/CreatePerson.js +0 -100
  25. package/dist/components/CreatePerson.js.map +0 -1
  26. package/dist/components/PersonAdd.d.ts +0 -16
  27. package/dist/components/PersonAdd.d.ts.map +0 -1
  28. package/dist/components/PersonAdd.js +0 -52
  29. package/dist/components/PersonAdd.js.map +0 -1
  30. package/dist/donationComponents/DonationPage.d.ts +0 -11
  31. package/dist/donationComponents/DonationPage.d.ts.map +0 -1
  32. package/dist/donationComponents/DonationPage.js +0 -149
  33. package/dist/donationComponents/DonationPage.js.map +0 -1
  34. package/dist/donationComponents/components/BankForm.d.ts +0 -14
  35. package/dist/donationComponents/components/BankForm.d.ts.map +0 -1
  36. package/dist/donationComponents/components/BankForm.js +0 -125
  37. package/dist/donationComponents/components/BankForm.js.map +0 -1
  38. package/dist/donationComponents/components/CardForm.d.ts +0 -13
  39. package/dist/donationComponents/components/CardForm.d.ts.map +0 -1
  40. package/dist/donationComponents/components/CardForm.js +0 -122
  41. package/dist/donationComponents/components/CardForm.js.map +0 -1
  42. package/dist/donationComponents/components/DonationForm.d.ts +0 -15
  43. package/dist/donationComponents/components/DonationForm.d.ts.map +0 -1
  44. package/dist/donationComponents/components/DonationForm.js +0 -200
  45. package/dist/donationComponents/components/DonationForm.js.map +0 -1
  46. package/dist/donationComponents/components/FundDonation.d.ts +0 -12
  47. package/dist/donationComponents/components/FundDonation.d.ts.map +0 -1
  48. package/dist/donationComponents/components/FundDonation.js +0 -32
  49. package/dist/donationComponents/components/FundDonation.js.map +0 -1
  50. package/dist/donationComponents/components/FundDonations.d.ts +0 -11
  51. package/dist/donationComponents/components/FundDonations.d.ts.map +0 -1
  52. package/dist/donationComponents/components/FundDonations.js +0 -33
  53. package/dist/donationComponents/components/FundDonations.js.map +0 -1
  54. package/dist/donationComponents/components/NonAuthDonation.d.ts +0 -12
  55. package/dist/donationComponents/components/NonAuthDonation.d.ts.map +0 -1
  56. package/dist/donationComponents/components/NonAuthDonation.js +0 -27
  57. package/dist/donationComponents/components/NonAuthDonation.js.map +0 -1
  58. package/dist/donationComponents/components/NonAuthDonationInner.d.ts +0 -12
  59. package/dist/donationComponents/components/NonAuthDonationInner.d.ts.map +0 -1
  60. package/dist/donationComponents/components/NonAuthDonationInner.js +0 -276
  61. package/dist/donationComponents/components/NonAuthDonationInner.js.map +0 -1
  62. package/dist/donationComponents/components/PaymentMethods.d.ts +0 -14
  63. package/dist/donationComponents/components/PaymentMethods.d.ts.map +0 -1
  64. package/dist/donationComponents/components/PaymentMethods.js +0 -86
  65. package/dist/donationComponents/components/PaymentMethods.js.map +0 -1
  66. package/dist/donationComponents/components/RecurringDonations.d.ts +0 -10
  67. package/dist/donationComponents/components/RecurringDonations.d.ts.map +0 -1
  68. package/dist/donationComponents/components/RecurringDonations.js +0 -93
  69. package/dist/donationComponents/components/RecurringDonations.js.map +0 -1
  70. package/dist/donationComponents/components/RecurringDonationsEdit.d.ts +0 -11
  71. package/dist/donationComponents/components/RecurringDonationsEdit.d.ts.map +0 -1
  72. package/dist/donationComponents/components/RecurringDonationsEdit.js +0 -66
  73. package/dist/donationComponents/components/RecurringDonationsEdit.js.map +0 -1
  74. package/dist/donationComponents/components/index.d.ts +0 -10
  75. package/dist/donationComponents/components/index.d.ts.map +0 -1
  76. package/dist/donationComponents/components/index.js +0 -22
  77. package/dist/donationComponents/components/index.js.map +0 -1
  78. package/dist/donationComponents/index.d.ts +0 -4
  79. package/dist/donationComponents/index.d.ts.map +0 -1
  80. package/dist/donationComponents/index.js +0 -10
  81. package/dist/donationComponents/index.js.map +0 -1
  82. package/dist/donationComponents/modals/DonationPreviewModal.d.ts +0 -15
  83. package/dist/donationComponents/modals/DonationPreviewModal.d.ts.map +0 -1
  84. package/dist/donationComponents/modals/DonationPreviewModal.js +0 -33
  85. package/dist/donationComponents/modals/DonationPreviewModal.js.map +0 -1
  86. package/src/components/CreatePerson.tsx +0 -135
  87. package/src/components/PersonAdd.tsx +0 -81
  88. package/src/donationComponents/DonationPage.tsx +0 -214
  89. package/src/donationComponents/components/BankForm.tsx +0 -161
  90. package/src/donationComponents/components/CardForm.tsx +0 -106
  91. package/src/donationComponents/components/DonationForm.tsx +0 -255
  92. package/src/donationComponents/components/FundDonation.tsx +0 -58
  93. package/src/donationComponents/components/FundDonations.tsx +0 -44
  94. package/src/donationComponents/components/NonAuthDonation.tsx +0 -33
  95. package/src/donationComponents/components/NonAuthDonationInner.tsx +0 -295
  96. package/src/donationComponents/components/PaymentMethods.tsx +0 -137
  97. package/src/donationComponents/components/RecurringDonations.tsx +0 -123
  98. package/src/donationComponents/components/RecurringDonationsEdit.tsx +0 -95
  99. package/src/donationComponents/components/index.tsx +0 -9
  100. package/src/donationComponents/index.ts +0 -3
  101. package/src/donationComponents/modals/DonationPreviewModal.tsx +0 -68
@@ -1,214 +0,0 @@
1
- "use client";
2
-
3
- import React from "react";
4
- import { loadStripe, Stripe } from "@stripe/stripe-js";
5
- import { DonationForm, RecurringDonations, PaymentMethods } from "./components";
6
- import { DisplayBox, ExportLink, Loading } from "../components";
7
- import { ApiHelper, DateHelper, UniqueIdHelper, CurrencyHelper, Locale } from "../helpers";
8
- import { DonationInterface, PersonInterface, StripePaymentMethod, ChurchInterface } from "@churchapps/helpers";
9
- // import { Link } from "react-router-dom"
10
- import { Table, TableBody, TableRow, TableCell, TableHead, Alert, Button, Icon, Link, Menu, MenuItem } from "@mui/material"
11
- import { useMountedState } from "../hooks/useMountedState";
12
-
13
- interface Props { personId: string, appName?: string, church?: ChurchInterface, churchLogo?: string }
14
-
15
- export const DonationPage: React.FC<Props> = (props) => {
16
- const [donations, setDonations] = React.useState<DonationInterface[]>(null);
17
- const [stripePromise, setStripe] = React.useState<Promise<Stripe>>(null);
18
- const [paymentMethods, setPaymentMethods] = React.useState<StripePaymentMethod[]>(null);
19
- const [customerId, setCustomerId] = React.useState(null);
20
- const [person, setPerson] = React.useState<PersonInterface>(null);
21
- const [message, setMessage] = React.useState<string>(null);
22
- const [appName, setAppName] = React.useState<string>("");
23
- const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
24
- const open = Boolean(anchorEl);
25
- const isMounted = useMountedState();
26
-
27
- const handleClose = () => {
28
- setAnchorEl(null);
29
- }
30
-
31
- const loadPaymentMethods = async () => {
32
- try {
33
- const data = await ApiHelper.get("/paymentmethods/personid/" + props.personId, "GivingApi");
34
- if (!data.length) {
35
- setPaymentMethods([]);
36
- return;
37
- }
38
-
39
- const cards = data[0].cards.data.map((card: any) => new StripePaymentMethod(card));
40
- const banks = data[0].banks.data.map((bank: any) => new StripePaymentMethod(bank));
41
- setCustomerId(data[0].customer.id);
42
- setPaymentMethods(cards.concat(banks));
43
- } catch (error) {
44
- console.error("Error loading payment methods:", error);
45
- setPaymentMethods([]);
46
- }
47
- }
48
-
49
- const loadPersonData = async () => {
50
- try {
51
- const data = await ApiHelper.get("/people/" + props.personId, "MembershipApi");
52
- setPerson(data);
53
- } catch (error) {
54
- console.error("Error loading person data:", error);
55
- }
56
- }
57
-
58
- const loadStripeData = async (gatewayData: any) => {
59
- if (!gatewayData.length || !gatewayData[0]?.publicKey) {
60
- setPaymentMethods([]);
61
- return;
62
- }
63
-
64
- setStripe(loadStripe(gatewayData[0].publicKey));
65
- await Promise.all([
66
- loadPersonData(),
67
- loadPaymentMethods()
68
- ]);
69
- }
70
-
71
- const loadData = async () => {
72
- if (props?.appName) setAppName(props.appName);
73
- if (UniqueIdHelper.isMissing(props.personId)) return;
74
-
75
- try {
76
- const [donationsData, gatewaysData] = await Promise.all([
77
- ApiHelper.get("/donations?personId=" + props.personId, "GivingApi"),
78
- ApiHelper.get("/gateways", "GivingApi")
79
- ]);
80
-
81
- setDonations(donationsData);
82
- await loadStripeData(gatewaysData);
83
- } catch (error) {
84
- console.error("Error loading donation data:", error);
85
- setDonations([]);
86
- setPaymentMethods([]);
87
- }
88
- }
89
-
90
- const handleDataUpdate = (message?: string) => {
91
- setMessage(message)
92
- setPaymentMethods(null);
93
- loadData();
94
- }
95
-
96
- const getEditContent = () => {
97
- const result: React.ReactElement[] = [];
98
- const date = new Date();
99
- const currentY = date.getFullYear();
100
- const lastY = date.getFullYear() - 1;
101
-
102
- const current_year = (donations.length>0) ? donations.filter(d => new Date(d.donationDate || "2000-01-01").getFullYear() === currentY) : [];
103
- const last_year = (donations.length>0) ? donations.filter(d => new Date(d.donationDate || "2000-01-01").getFullYear() === lastY) : [];
104
- const customHeaders = [
105
- { label: "amount", key: "amount" },
106
- { label: "donationDate", key: "donationDate" },
107
- { label: "fundName", key: "fund.name" },
108
- { label: "method", key: "method"},
109
- { label: "methodDetails", key: "methodDetails"},
110
- ]
111
-
112
- result.push(<>
113
- <Button
114
- id="download-button"
115
- aria-controls={open ? "download-menu" : undefined}
116
- aria-haspopup="true"
117
- aria-expanded={open ? "true" : undefined}
118
- onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
119
- setAnchorEl(e.currentTarget);
120
- }}
121
- >
122
- <Icon>download</Icon>
123
- </Button>
124
- <Menu
125
- id="download-menu"
126
- anchorEl={anchorEl}
127
- open={open}
128
- onClose={handleClose}
129
- MenuListProps={{ 'aria-labelledby': "download-button" }}
130
- >
131
- <MenuItem onClick={handleClose} dense><ExportLink data={current_year} filename="current_year_donations" customHeaders={customHeaders} text="Current Year (CSV)" icon="table_chart" /></MenuItem>
132
- <MenuItem onClick={handleClose} dense><Link href={"/donations/print/" + person?.id}><Button><Icon>print</Icon> &nbsp; Current Year (PRINT)</Button></Link></MenuItem>
133
- <MenuItem onClick={handleClose} dense><ExportLink data={last_year} filename="last_year_donations" customHeaders={customHeaders} text="Last Year (CSV)" icon="table_chart" /></MenuItem>
134
- <MenuItem onClick={handleClose} dense><Link href={"/donations/print/" + person?.id + "?prev=1"}><Button><Icon>print</Icon> &nbsp; Last Year (PRINT)</Button></Link></MenuItem>
135
- </Menu>
136
- </>);
137
-
138
- return result;
139
- }
140
-
141
- const getRows = () => {
142
- let rows: React.ReactElement[] = [];
143
-
144
- if (donations.length === 0) {
145
- rows.push(<TableRow key="0"><TableCell>{Locale.label("donation.page.willAppear")}</TableCell></TableRow>);
146
- return rows;
147
- }
148
-
149
- for (let i = 0; i < donations.length; i++) {
150
- let d = donations[i];
151
- rows.push(
152
- <TableRow key={i}>
153
- {appName !== "B1App" && <TableCell><Link href={"/donations/" + d.batchId}>{d.batchId}</Link></TableCell>}
154
- <TableCell>{DateHelper.prettyDate(new Date(d.donationDate))}</TableCell>
155
- <TableCell>{d.method} - {d.methodDetails}</TableCell>
156
- <TableCell>{d.fund.name}</TableCell>
157
- <TableCell>{CurrencyHelper.formatCurrency(d.fund.amount)}</TableCell>
158
- </TableRow>
159
- );
160
- }
161
- return rows;
162
- }
163
-
164
- const getTableHeader = () => {
165
- const rows: React.ReactElement[] = []
166
-
167
- if (donations.length > 0) {
168
- rows.push(
169
- <TableRow key="header" sx={{textAlign: "left"}}>
170
- {appName !== "B1App" && <th>{Locale.label("donation.page.batch")}</th>}
171
- <th>{Locale.label("donation.page.date")}</th>
172
- <th>{Locale.label("donation.page.method")}</th>
173
- <th>{Locale.label("donation.page.fund")}</th>
174
- <th>{Locale.label("donation.page.amount")}</th>
175
- </TableRow>
176
- );
177
- }
178
-
179
- return rows;
180
- }
181
-
182
- React.useEffect(() => {
183
- loadData();
184
- }, [props.personId]); //eslint-disable-line
185
-
186
- const getTable = () => {
187
- if (!donations) return <Loading />;
188
- else return (<Table>
189
- <TableHead>{getTableHeader()}</TableHead>
190
- <TableBody>{getRows()}</TableBody>
191
- </Table>);
192
- }
193
-
194
- const getPaymentMethodComponents = () => {
195
- if (!paymentMethods || !donations) return <Loading />;
196
- else return (
197
- <>
198
- <DonationForm person={person} customerId={customerId} paymentMethods={paymentMethods} stripePromise={stripePromise} donationSuccess={handleDataUpdate} church={props?.church} churchLogo={props?.churchLogo} />
199
- <DisplayBox headerIcon="payments" headerText="Donations" editContent={getEditContent()}>
200
- {getTable()}
201
- </DisplayBox>
202
- <RecurringDonations customerId={customerId} paymentMethods={paymentMethods} appName={appName} dataUpdate={handleDataUpdate} />
203
- <PaymentMethods person={person} customerId={customerId} paymentMethods={paymentMethods} appName={appName} stripePromise={stripePromise} dataUpdate={handleDataUpdate} />
204
- </>
205
- );
206
- }
207
-
208
- return (
209
- <>
210
- {paymentMethods && message && <Alert severity="success">{message}</Alert>}
211
- {getPaymentMethodComponents()}
212
- </>
213
- );
214
- }
@@ -1,161 +0,0 @@
1
- "use client";
2
-
3
- import React from "react";
4
- import { FormControl, Grid, InputLabel, MenuItem, Select, SelectChangeEvent, TextField } from "@mui/material"
5
- import { useStripe } from "@stripe/react-stripe-js";
6
- import { InputBox, ErrorMessages } from "../../components";
7
- import { ApiHelper, Locale } from "../../helpers";
8
- import { PersonInterface, StripePaymentMethod, PaymentMethodInterface, StripeBankAccountInterface, StripeBankAccountUpdateInterface, StripeBankAccountVerifyInterface } from "@churchapps/helpers";
9
-
10
- interface Props { bank: StripePaymentMethod, showVerifyForm: boolean, customerId: string, person: PersonInterface, setMode: any, deletePayment: any, updateList: (message?: string) => void }
11
-
12
- export const BankForm: React.FC<Props> = (props) => {
13
- const stripe = useStripe();
14
- const [bankAccount, setBankAccount] = React.useState<StripeBankAccountInterface>({ account_holder_name: props.bank.account_holder_name, account_holder_type: props.bank.account_holder_type, country: "US", currency: "usd" } as StripeBankAccountInterface);
15
- const [paymentMethod] = React.useState<PaymentMethodInterface>({ customerId: props.customerId, personId: props.person.id, email: props.person.contactInfo.email, name: props.person.name.display });
16
- const [updateBankData] = React.useState<StripeBankAccountUpdateInterface>({ paymentMethodId: props.bank.id, customerId: props.customerId, personId: props.person.id, bankData: { account_holder_name: props.bank.account_holder_name, account_holder_type: props.bank.account_holder_type } } as StripeBankAccountUpdateInterface);
17
- const [verifyBankData, setVerifyBankData] = React.useState<StripeBankAccountVerifyInterface>({ paymentMethodId: props.bank.id, customerId: props.customerId, amountData: { amounts: [] } });
18
- const [showSave, setShowSave] = React.useState<boolean>(true);
19
- const [errorMessage, setErrorMessage] = React.useState<string>(null);
20
- const saveDisabled = () => { }
21
- const handleCancel = () => { props.setMode("display"); }
22
- const handleDelete = () => { props.deletePayment(); }
23
- const handleSave = () => {
24
- setShowSave(false);
25
- if (props.showVerifyForm) verifyBank();
26
- else props.bank.id ? updateBank() : createBank();
27
- }
28
-
29
- const createBank = async () => {
30
- if (!bankAccount.routing_number || !bankAccount.account_number) setErrorMessage(Locale.label("donation.bankForm.validate.accountNumber"))
31
- else {
32
- await stripe.createToken("bank_account", bankAccount).then(response => {
33
- if (response?.error?.message) setErrorMessage(response.error.message);
34
- else {
35
- const pm = { ...paymentMethod };
36
- pm.id = response.token.id;
37
- ApiHelper.post("/paymentmethods/addbankaccount", pm, "GivingApi").then(result => {
38
- if (result?.raw?.message) setErrorMessage(result.raw.message);
39
- else {
40
- props.updateList(Locale.label("donation.bankForm.added"));
41
- props.setMode("display");
42
- }
43
- });
44
- }
45
- });
46
- }
47
- setShowSave(true);
48
- }
49
-
50
- const updateBank = () => {
51
- if (bankAccount.account_holder_name === "") setErrorMessage(Locale.label("donation.bankForm.validate.holderName"));
52
- else {
53
- let bank = { ...updateBankData };
54
- bank.bankData.account_holder_name = bankAccount.account_holder_name;
55
- bank.bankData.account_holder_type = bankAccount.account_holder_type;
56
- ApiHelper.post("/paymentmethods/updatebank", bank, "GivingApi").then(response => {
57
- if (response?.raw?.message) setErrorMessage(response.raw.message);
58
- else {
59
- props.updateList(Locale.label("donation.bankForm.updated"));
60
- props.setMode("display");
61
- }
62
- });
63
- }
64
- setShowSave(true);
65
- }
66
-
67
- const verifyBank = () => {
68
- const amounts = verifyBankData?.amountData?.amounts;
69
- if (amounts && amounts.length === 2 && amounts[0] !== "" && amounts[1] !== "") {
70
- ApiHelper.post("/paymentmethods/verifyBank", verifyBankData, "GivingApi").then(response => {
71
- if (response?.raw?.message) setErrorMessage(response.raw.message);
72
- else {
73
- props.updateList(Locale.label("donation.bankForm.verified"));
74
- props.setMode("display");
75
- }
76
- });
77
- }
78
- else setErrorMessage("Both deposit amounts are required.");
79
- setShowSave(true);
80
- }
81
-
82
- const getHeaderText = () => props.bank.id
83
- ? `${props.bank.name.toUpperCase()} ****${props.bank.last4}`
84
- : "Add New Bank Account"
85
-
86
- const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | SelectChangeEvent<string>) => {
87
- const bankData = { ...bankAccount };
88
- const inputData = { [e.target.name]: e.target.value };
89
- setBankAccount({ ...bankData, ...inputData });
90
- setShowSave(true);
91
- }
92
-
93
- const handleKeyPress = (e: React.KeyboardEvent<any>) => {
94
- const pattern = /^\d+$/;
95
- if (!pattern.test(e.key)) e.preventDefault();
96
- }
97
-
98
- const handleVerify = (e: React.ChangeEvent<HTMLInputElement>) => {
99
- const verifyData = { ...verifyBankData };
100
- if (e.currentTarget.name === "amount1") verifyData.amountData.amounts[0] = e.currentTarget.value;
101
- if (e.currentTarget.name === "amount2") verifyData.amountData.amounts[1] = e.currentTarget.value;
102
- setVerifyBankData(verifyData);
103
- }
104
-
105
- const getForm = () => {
106
- if (props.showVerifyForm) {
107
- return (<>
108
- <p>{Locale.label("donation.bankForm.twoDeposits")}</p>
109
- <Grid container columnSpacing={2}>
110
- <Grid size={{ xs: 12, md: 6 }}>
111
- <TextField fullWidth aria-label="amount1" label={Locale.label("donation.bankForm.firstDeposit")} name="amount1" placeholder="00" inputProps={{ maxLength: 2 }} onChange={handleVerify} onKeyPress={handleKeyPress} />
112
- </Grid>
113
- <Grid size={{ xs: 12, md: 6 }}>
114
- <TextField fullWidth aria-label="amount2" label={Locale.label("donation.bankForm.secondDeposit")} name="amount2" placeholder="00" inputProps={{ maxLength: 2 }} onChange={handleVerify} onKeyPress={handleKeyPress} />
115
- </Grid>
116
- </Grid>
117
- </>);
118
-
119
- } else {
120
- let accountDetails = <></>
121
- if (!props.bank.id) accountDetails = (
122
- <Grid container spacing={3}>
123
- <Grid size={{ xs: 12, md: 6 }} style={{ marginBottom: "20px" }}>
124
- <TextField fullWidth label={Locale.label("donation.bankForm.routingNumber")} type="number" name="routing_number" aria-label="routing-number" placeholder="Routing Number" className="form-control" onChange={handleChange} />
125
- </Grid>
126
- <Grid size={{ xs: 12, md: 6 }} style={{ marginBottom: "20px" }}>
127
- <TextField fullWidth label={Locale.label("donation.bankForm.accountNumber")} type="number" name="account_number" aria-label="account-number" placeholder="Account Number" className="form-control" onChange={handleChange} />
128
- </Grid>
129
- </Grid>
130
- );
131
- return (<>
132
- <Grid container spacing={3}>
133
- <Grid size={{ xs: 12, md: 6 }} style={{ marginBottom: "20px" }}>
134
- <TextField fullWidth label="Account Holder Name" name="account_holder_name" required aria-label="account-holder-name" placeholder="Account Holder Name" value={bankAccount.account_holder_name} className="form-control" onChange={handleChange} />
135
- </Grid>
136
- <Grid size={{ xs: 12, md: 6 }} style={{ marginBottom: "20px" }}>
137
- <FormControl fullWidth>
138
- <InputLabel>{Locale.label("donation.bankForm.name")}</InputLabel>
139
- <Select label={Locale.label("donation.bankForm.name")} name="account_holder_type" aria-label="account-holder-type" value={bankAccount.account_holder_type} onChange={handleChange}>
140
- <MenuItem value="individual">{Locale.label("donation.bankForm.individual")}</MenuItem>
141
- <MenuItem value="company">{Locale.label("donation.bankForm.company")}</MenuItem>
142
- </Select>
143
- </FormControl>
144
- </Grid>
145
- </Grid>
146
- {accountDetails}
147
- </>);
148
- }
149
- }
150
-
151
- return (
152
- <InputBox headerIcon="volunteer_activism" headerText={getHeaderText()} ariaLabelSave="save-button" ariaLabelDelete="delete-button" cancelFunction={handleCancel} saveFunction={showSave ? handleSave : saveDisabled} deleteFunction={props.bank.id && !props.showVerifyForm ? handleDelete : undefined}>
153
- {errorMessage && <ErrorMessages errors={[errorMessage]}></ErrorMessages>}
154
- <div>
155
- {!props.bank.id && <p>{Locale.label("donation.bankForm.needVerified")}</p>}
156
- {getForm()}
157
- </div>
158
- </InputBox>
159
- );
160
-
161
- }
@@ -1,106 +0,0 @@
1
- "use client";
2
-
3
- import React, { useEffect } from "react";
4
- import { Grid, TextField } from "@mui/material"
5
- import { CardElement, useStripe, useElements } from "@stripe/react-stripe-js";
6
- import { InputBox, ErrorMessages } from "../../components";
7
- import { ApiHelper, Locale } from "../../helpers";
8
- import { PersonInterface, StripePaymentMethod, PaymentMethodInterface, StripeCardUpdateInterface } from "@churchapps/helpers";
9
-
10
- interface Props { card: StripePaymentMethod, customerId: string, person: PersonInterface, setMode: any, deletePayment: any, updateList: (message: string) => void }
11
-
12
- export const CardForm: React.FC<Props> = (props) => {
13
- const stripe = useStripe();
14
- const elements = useElements();
15
- const formStyling = { style: { base: { fontSize: "18px" } } };
16
- const [showSave, setShowSave] = React.useState(true);
17
- const [paymentMethod] = React.useState<PaymentMethodInterface>({ id: props.card.id, customerId: props.customerId, personId: props.person.id, email: props.person.contactInfo.email, name: props.person.name.display });
18
- const [cardUpdate, setCardUpdate] = React.useState<StripeCardUpdateInterface>({ personId: props.person.id, paymentMethodId: props.card.id, cardData: { card: {} } } as StripeCardUpdateInterface);
19
- const [errorMessage, setErrorMessage] = React.useState<string>(null);
20
- const handleCancel = () => { props.setMode("display"); }
21
- const handleSave = () => { setShowSave(false); props.card.id ? updateCard() : createCard(); }
22
- const saveDisabled = () => { }
23
- const handleDelete = () => { props.deletePayment(); }
24
-
25
- const handleKeyPress = (e: React.KeyboardEvent<any>) => {
26
- const pattern = /^\d+$/;
27
- if (!pattern.test(e.key)) e.preventDefault();
28
- }
29
-
30
- useEffect(() => {
31
- setCardUpdate({ ...cardUpdate, cardData: { card: { exp_year: props.card?.exp_year?.toString().slice(2) || "", exp_month: props.card?.exp_month || "" } } });
32
- }, []) //eslint-disable-line
33
-
34
- const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
35
- const card = { ...cardUpdate };
36
- if (e.currentTarget.name === "exp_month") card.cardData.card.exp_month = e.currentTarget.value;
37
- if (e.currentTarget.name === "exp_year") card.cardData.card.exp_year = e.currentTarget.value;
38
- setCardUpdate(card);
39
- setShowSave(true);
40
- }
41
-
42
- const createCard = async () => {
43
- const cardData = elements.getElement(CardElement);
44
- const stripePM = await stripe.createPaymentMethod({
45
- type: "card",
46
- card: cardData
47
- });
48
- if (stripePM.error) {
49
- setErrorMessage(stripePM.error.message);
50
- setShowSave(true);
51
- } else {
52
- let pm = { ...paymentMethod };
53
- pm.id = stripePM.paymentMethod.id;
54
- await ApiHelper.post("/paymentmethods/addcard", pm, "GivingApi").then(result => {
55
- if (result?.raw?.message) {
56
- setErrorMessage(result.raw.message);
57
- setShowSave(true);
58
- }
59
- else {
60
- props.updateList(Locale.label("donation.cardForm.added"));
61
- props.setMode("display");
62
- }
63
- });
64
- }
65
- }
66
-
67
- const updateCard = async () => {
68
- if (!cardUpdate.cardData.card.exp_month || !cardUpdate.cardData.card.exp_year) setErrorMessage("Expiration month and year cannot be blank.");
69
- else {
70
- await ApiHelper.post("/paymentmethods/updatecard", cardUpdate, "GivingApi").then(result => {
71
- if (result?.raw?.message) {
72
- setErrorMessage(result.raw.message);
73
- setShowSave(true);
74
- }
75
- else {
76
- props.updateList(Locale.label("donation.cardForm.updated"));
77
- props.setMode("display");
78
- }
79
- });
80
- }
81
- }
82
-
83
- const getHeaderText = () => props.card.id
84
- ? `${props.card.name.toUpperCase()} ****${props.card.last4}`
85
- : Locale.label("donation.cardForm.addNew")
86
-
87
- return (
88
- <InputBox headerIcon="volunteer_activism" headerText={getHeaderText()} ariaLabelSave="save-button" ariaLabelDelete="delete-button" cancelFunction={handleCancel} saveFunction={showSave ? handleSave : saveDisabled} deleteFunction={props.card.id ? handleDelete : undefined}>
89
- {errorMessage && <ErrorMessages errors={[errorMessage]}></ErrorMessages>}
90
- <div>
91
- {!props.card.id
92
- ? <CardElement options={formStyling} />
93
- : <Grid container spacing={3}>
94
- <Grid size={{ xs: 12, md: 6 }}>
95
- <TextField fullWidth aria-label="card-exp-month" label={Locale.label("donation.cardForm.expirationMonth")} name="exp_month" value={cardUpdate.cardData.card.exp_month} placeholder="MM" inputProps={{ maxLength: 2 }} onChange={handleChange} onKeyPress={handleKeyPress} />
96
- </Grid>
97
- <Grid size={{ xs: 12, md: 6 }}>
98
- <TextField fullWidth aria-label="card-exp-year" label={Locale.label("donation.cardForm.expirationYear")} name="exp_year" value={cardUpdate.cardData.card.exp_year} placeholder="YY" inputProps={{ maxLength: 2 }} onChange={handleChange} onKeyPress={handleKeyPress} />
99
- </Grid>
100
- </Grid>
101
- }
102
- </div>
103
- </InputBox>
104
- );
105
-
106
- }