@churchapps/apphelper 0.4.9 → 0.4.10

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 (66) hide show
  1. package/dist/components/ImageEditor.d.ts +0 -1
  2. package/dist/components/ImageEditor.d.ts.map +1 -1
  3. package/dist/components/ImageEditor.js +1 -1
  4. package/dist/components/ImageEditor.js.map +1 -1
  5. package/dist/donationComponents/components/BankForm.d.ts +14 -0
  6. package/dist/donationComponents/components/BankForm.d.ts.map +1 -0
  7. package/dist/donationComponents/components/BankForm.js +126 -0
  8. package/dist/donationComponents/components/BankForm.js.map +1 -0
  9. package/dist/donationComponents/components/CardForm.d.ts +13 -0
  10. package/dist/donationComponents/components/CardForm.d.ts.map +1 -0
  11. package/dist/donationComponents/components/CardForm.js +122 -0
  12. package/dist/donationComponents/components/CardForm.js.map +1 -0
  13. package/dist/donationComponents/components/DonationForm.d.ts +15 -0
  14. package/dist/donationComponents/components/DonationForm.d.ts.map +1 -0
  15. package/dist/donationComponents/components/DonationForm.js +199 -0
  16. package/dist/donationComponents/components/DonationForm.js.map +1 -0
  17. package/dist/donationComponents/components/FundDonation.d.ts +12 -0
  18. package/dist/donationComponents/components/FundDonation.d.ts.map +1 -0
  19. package/dist/donationComponents/components/FundDonation.js +32 -0
  20. package/dist/donationComponents/components/FundDonation.js.map +1 -0
  21. package/dist/donationComponents/components/FundDonations.d.ts +11 -0
  22. package/dist/donationComponents/components/FundDonations.d.ts.map +1 -0
  23. package/dist/donationComponents/components/FundDonations.js +33 -0
  24. package/dist/donationComponents/components/FundDonations.js.map +1 -0
  25. package/dist/donationComponents/components/PaymentMethods.d.ts +14 -0
  26. package/dist/donationComponents/components/PaymentMethods.d.ts.map +1 -0
  27. package/dist/donationComponents/components/PaymentMethods.js +84 -0
  28. package/dist/donationComponents/components/PaymentMethods.js.map +1 -0
  29. package/dist/donationComponents/components/RecurringDonations.d.ts +10 -0
  30. package/dist/donationComponents/components/RecurringDonations.d.ts.map +1 -0
  31. package/dist/donationComponents/components/RecurringDonations.js +93 -0
  32. package/dist/donationComponents/components/RecurringDonations.js.map +1 -0
  33. package/dist/donationComponents/components/RecurringDonationsEdit.d.ts +11 -0
  34. package/dist/donationComponents/components/RecurringDonationsEdit.d.ts.map +1 -0
  35. package/dist/donationComponents/components/RecurringDonationsEdit.js +66 -0
  36. package/dist/donationComponents/components/RecurringDonationsEdit.js.map +1 -0
  37. package/dist/donationComponents/components/index.d.ts +9 -0
  38. package/dist/donationComponents/components/index.d.ts.map +1 -0
  39. package/dist/donationComponents/components/index.js +20 -0
  40. package/dist/donationComponents/components/index.js.map +1 -0
  41. package/dist/donationComponents/index.d.ts +3 -0
  42. package/dist/donationComponents/index.d.ts.map +1 -0
  43. package/dist/donationComponents/index.js +21 -0
  44. package/dist/donationComponents/index.js.map +1 -0
  45. package/dist/donationComponents/modals/DonationPreviewModal.d.ts +15 -0
  46. package/dist/donationComponents/modals/DonationPreviewModal.d.ts.map +1 -0
  47. package/dist/donationComponents/modals/DonationPreviewModal.js +33 -0
  48. package/dist/donationComponents/modals/DonationPreviewModal.js.map +1 -0
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -0
  52. package/dist/index.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/components/ImageEditor.tsx +1 -1
  55. package/src/donationComponents/components/BankForm.tsx +163 -0
  56. package/src/donationComponents/components/CardForm.tsx +104 -0
  57. package/src/donationComponents/components/DonationForm.tsx +260 -0
  58. package/src/donationComponents/components/FundDonation.tsx +59 -0
  59. package/src/donationComponents/components/FundDonations.tsx +44 -0
  60. package/src/donationComponents/components/PaymentMethods.tsx +133 -0
  61. package/src/donationComponents/components/RecurringDonations.tsx +117 -0
  62. package/src/donationComponents/components/RecurringDonationsEdit.tsx +96 -0
  63. package/src/donationComponents/components/index.tsx +8 -0
  64. package/src/donationComponents/index.ts +2 -0
  65. package/src/donationComponents/modals/DonationPreviewModal.tsx +70 -0
  66. package/src/index.ts +1 -0
@@ -0,0 +1,44 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { FundDonation } from ".";
5
+ import { FundDonationInterface, FundInterface } from "@churchapps/helpers";
6
+ import { Locale } from "../../helpers";
7
+
8
+ interface Props { fundDonations: FundDonationInterface[], funds: FundInterface[], params?: any, updatedFunction: (fundDonations: FundDonationInterface[]) => void }
9
+
10
+ export const FundDonations: React.FC<Props> = (props) => {
11
+ const handleUpdated = (fundDonation: FundDonationInterface, index: number) => {
12
+ const fundDonations = [...props.fundDonations];
13
+ fundDonations[index] = fundDonation;
14
+ props.updatedFunction(fundDonations);
15
+ };
16
+
17
+ const addRow = (e: React.MouseEvent) => {
18
+ e.preventDefault();
19
+ const fundDonations = [...props.fundDonations];
20
+ const fd = { fundId: props.funds[0].id } as FundDonationInterface;
21
+ fundDonations.push(fd);
22
+ props.updatedFunction(fundDonations);
23
+ };
24
+
25
+ const getRows = () => {
26
+ const result = [];
27
+ for (let i = 0; i < props.fundDonations.length; i++) {
28
+ const fd = props.fundDonations[i];
29
+ result.push(<FundDonation fundDonation={fd} funds={props.funds} updatedFunction={handleUpdated} params={props?.params} key={i} index={i} />);
30
+ }
31
+
32
+ return result;
33
+ };
34
+
35
+ return (
36
+ <>
37
+ {getRows()}
38
+ {(!props?.params?.fundId || props?.params?.fundId === "") &&
39
+ <a href="about:blank" aria-label="add-fund-donation" className="text-decoration" style={{ display: "block", marginBottom: "15px" }} onClick={addRow}>{Locale.label("donation.fundDonations.addMore")}</a>
40
+ }
41
+ </>
42
+ );
43
+ };
44
+
@@ -0,0 +1,133 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import type { Stripe } from "@stripe/stripe-js";
5
+ import { Elements } from "@stripe/react-stripe-js";
6
+ import { CardForm, BankForm } from ".";
7
+ import { DisplayBox, Loading } from "../../components";
8
+ import { ApiHelper, Locale, UserHelper } from "../../helpers";
9
+ import { PersonInterface, StripePaymentMethod, Permissions } from "@churchapps/helpers";
10
+ import {
11
+ Icon, Table, TableBody, TableCell, TableRow, IconButton, Menu, MenuItem
12
+ } from "@mui/material";
13
+
14
+ interface Props { person: PersonInterface, customerId: string, paymentMethods: StripePaymentMethod[], stripePromise: Promise<Stripe>, appName: string, dataUpdate: (message?: string) => void }
15
+
16
+ export const PaymentMethods: React.FC<Props> = (props) => {
17
+ const [editPaymentMethod, setEditPaymentMethod] = React.useState<StripePaymentMethod>(new StripePaymentMethod());
18
+ const [mode, setMode] = React.useState("display");
19
+ const [verify, setVerify] = React.useState<boolean>(false);
20
+
21
+ const handleEdit = (pm?: StripePaymentMethod, verifyAccount?: boolean) => (e: React.MouseEvent) => {
22
+ e.preventDefault();
23
+ setEditPaymentMethod(pm);
24
+ setVerify(verifyAccount);
25
+ setMode("edit");
26
+ };
27
+
28
+ const handleDelete = async () => {
29
+ const confirmed = window.confirm(Locale.label("donation.paymentMethods.confirmDelete"));
30
+ if (confirmed) {
31
+ ApiHelper.delete("/paymentmethods/" + editPaymentMethod.id + "/" + props.customerId, "GivingApi").then(() => {
32
+ setMode("display");
33
+ props.dataUpdate(Locale.label("donation.paymentMethods.deleted"));
34
+ });
35
+ }
36
+ };
37
+
38
+ const MenuIcon = () => {
39
+ const [anchorEl, setAnchorEl] = React.useState(null);
40
+ const open = Boolean(anchorEl);
41
+ const handleClick = (e: React.MouseEvent) => {
42
+ setAnchorEl(e.currentTarget);
43
+ };
44
+ const handleClose = () => {
45
+ setAnchorEl(null);
46
+ };
47
+ return (
48
+ <>
49
+ <IconButton
50
+ aria-label="add-button"
51
+ id="addBtnGroup"
52
+ aria-controls={open ? "add-menu" : undefined}
53
+ aria-expanded={open ? "true" : undefined}
54
+ aria-haspopup="true"
55
+ onClick={handleClick}
56
+ >
57
+ <Icon color="primary">add</Icon>
58
+ </IconButton>
59
+ <Menu
60
+ id="add-menu"
61
+ MenuListProps={{ "aria-labelledby": "addBtnGroup" }}
62
+ anchorEl={anchorEl}
63
+ open={open}
64
+ onClose={handleClose}
65
+ >
66
+ <MenuItem aria-label="add-card" onClick={handleEdit(new StripePaymentMethod({ type: "card" }))}>
67
+ <Icon sx={{ mr: "3px" }}>credit_card</Icon> {Locale.label("donation.paymentMethods.addCard")}
68
+ </MenuItem>
69
+ <MenuItem aria-label="add-bank" onClick={handleEdit(new StripePaymentMethod({ type: "bank" }))}>
70
+ <Icon sx={{ mr: "3px" }}>account_balance</Icon> {Locale.label("donation.paymentMethods.addBank")}
71
+ </MenuItem>
72
+ </Menu>
73
+ </>
74
+ );
75
+ };
76
+
77
+ const getNewContent = () => {
78
+ if (!UserHelper.checkAccess(Permissions.givingApi.settings.edit) && props.appName !== "B1App") return null;
79
+ return <MenuIcon />;
80
+ };
81
+
82
+ const getEditOptions = (pm: StripePaymentMethod) => {
83
+ if (!UserHelper.checkAccess(Permissions.givingApi.settings.edit) && props.appName !== "B1App") return null;
84
+ return <a aria-label="edit-button" onClick={handleEdit(pm)} href="about:blank"><Icon>edit</Icon></a>;
85
+ };
86
+
87
+ const getPMIcon = (type: string) => (type === "card" ? <Icon>credit_card</Icon> : <Icon>account_balance</Icon>);
88
+
89
+ const getPaymentRows = () => {
90
+ const rows: React.ReactElement[] = [];
91
+
92
+ props.paymentMethods.forEach((method: StripePaymentMethod) => {
93
+ rows.push(<TableRow key={method.id}>
94
+ <TableCell className="capitalize">{getPMIcon(method.type)} {method.name + " ****" + method.last4}</TableCell>
95
+ <TableCell>{method?.status === "new" && <a href="about:blank" aria-label="verify-account" onClick={handleEdit(method, true)}>{Locale.label("donation.paymentMethods.verify")}</a>}</TableCell>
96
+ <TableCell align="right">{getEditOptions(method)}</TableCell>
97
+ </TableRow>);
98
+ });
99
+ return rows;
100
+ };
101
+
102
+ const PaymentMethodsTable = () => {
103
+ if (!props.paymentMethods) return <Loading></Loading>;
104
+ if (props.paymentMethods.length) {
105
+ return (
106
+ <Table>
107
+ <TableBody>
108
+ {getPaymentRows()}
109
+ </TableBody>
110
+ </Table>
111
+ );
112
+ } else return <div>{Locale.label("donation.paymentMethods.noMethod")}</div>;
113
+ };
114
+
115
+ const EditForm = () => (
116
+ <Elements stripe={props.stripePromise}>
117
+ {editPaymentMethod.type === "card" && <CardForm card={editPaymentMethod} customerId={props.customerId} person={props.person} setMode={setMode} deletePayment={handleDelete} updateList={(message) => { props.dataUpdate(message); }} />}
118
+ {editPaymentMethod.type === "bank" && <BankForm bank={editPaymentMethod} showVerifyForm={verify} customerId={props.customerId} person={props.person} setMode={setMode} deletePayment={handleDelete} updateList={(message) => { props.dataUpdate(message); }} />}
119
+ </Elements>
120
+ );
121
+
122
+ const PaymentMethods = () => {
123
+ if (mode === "display") {
124
+ return (
125
+ <DisplayBox aria-label="payment-methods-box" headerIcon="credit_card" headerText="Payment Methods" editContent={getNewContent()}>
126
+ <PaymentMethodsTable></PaymentMethodsTable>
127
+ </DisplayBox>
128
+ );
129
+ } else return <EditForm></EditForm>;
130
+ };
131
+
132
+ return props.stripePromise ? <PaymentMethods></PaymentMethods> : null;
133
+ };
@@ -0,0 +1,117 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { DisplayBox } from "../../components";
5
+ import { ApiHelper, UserHelper, CurrencyHelper, DateHelper, Locale } from "../../helpers";
6
+ import { Permissions, SubscriptionInterface } from "@churchapps/helpers";
7
+ import { RecurringDonationsEdit } from ".";
8
+ import { Icon, Table, TableBody, TableCell, TableRow, TableHead } from "@mui/material";
9
+
10
+ interface Props { customerId: string, paymentMethods: any[], appName: string, dataUpdate: (message?: string) => void, };
11
+
12
+ export const RecurringDonations: React.FC<Props> = (props) => {
13
+ const [subscriptions, setSubscriptions] = React.useState<SubscriptionInterface[]>([]);
14
+ const [mode, setMode] = React.useState("display");
15
+ const [editSubscription, setEditSubscription] = React.useState<SubscriptionInterface>();
16
+
17
+ const loadData = () => {
18
+ if (props.customerId) {
19
+ ApiHelper.get("/customers/" + props.customerId + "/subscriptions", "GivingApi").then(subResult => {
20
+ const subs: SubscriptionInterface[] = [];
21
+ const requests = subResult.data?.map((s: any) => ApiHelper.get("/subscriptionfunds?subscriptionId=" + s.id, "GivingApi").then(subFunds => {
22
+ s.funds = subFunds;
23
+ subs.push(s);
24
+ }));
25
+ return requests && Promise.all(requests).then(() => {
26
+ setSubscriptions(subs);
27
+ });
28
+ });
29
+ }
30
+ };
31
+
32
+ const handleUpdate = (message: string) => {
33
+ loadData();
34
+ setMode("display");
35
+ if (message) props.dataUpdate(message);
36
+ };
37
+
38
+ const handleEdit = (sub: SubscriptionInterface) => (e: React.MouseEvent) => {
39
+ e.preventDefault();
40
+ setEditSubscription(sub);
41
+ setMode("edit");
42
+ };
43
+
44
+ const getPaymentMethod = (sub: SubscriptionInterface) => {
45
+ const pm = props.paymentMethods.find((pm: any) => pm.id === (sub.default_payment_method || sub.default_source));
46
+ if (!pm) return <span style={{ color: "red" }}>{Locale.label("donation.recurring.notFound")}</span>;
47
+ return `${pm.name} ****${pm.last4}`;
48
+ };
49
+
50
+ const getInterval = (subscription: SubscriptionInterface) => {
51
+ const interval = subscription.plan.interval_count + " " + subscription.plan.interval;
52
+ return subscription.plan.interval_count > 1 ? interval + "s" : interval;
53
+ };
54
+
55
+ const getFunds = (subscription: SubscriptionInterface) => {
56
+ const result: React.ReactElement[] = [];
57
+ subscription.funds.forEach((fund: any) => {
58
+ result.push(<div key={subscription.id + fund.id}>
59
+ {fund.name} <span style={{ float: "right" }}>{CurrencyHelper.formatCurrency(fund.amount)}</span>
60
+ </div>);
61
+ });
62
+ const total = (subscription.plan.amount / 100);
63
+ result.push(<div key={subscription.id + "-total"} style={{ borderTop: "solid #dee2e6 1px" }}>
64
+ Total <span style={{ float: "right" }}>{CurrencyHelper.formatCurrency(total)}</span>
65
+ </div>);
66
+ return result;
67
+ };
68
+
69
+ const getEditOptions = (sub: SubscriptionInterface) => {
70
+ if ((!UserHelper.checkAccess(Permissions.givingApi.settings.edit) && props.appName !== "B1App") || props?.paymentMethods?.length === 0) return null;
71
+ return <a aria-label="edit-button" onClick={handleEdit(sub)} href="about:blank"><Icon>edit</Icon></a>;
72
+ };
73
+
74
+ const getTableHeader = () => {
75
+ const result: React.ReactElement[] = [];
76
+ result.push(<TableRow key="header" sx={{ textAlign: "left" }}><TableCell><b>{Locale.label("donation.recurring.startDate")}</b></TableCell><TableCell><b>{Locale.label("donation.recurring.amount")}</b></TableCell><TableCell><b>{Locale.label("donation.recurring.interval")}</b></TableCell><TableCell><b>{Locale.label("donation.recurring.paymentMethod")}</b></TableCell>{props?.paymentMethods?.length > 0 && <TableCell></TableCell>}</TableRow>);
77
+ return result;
78
+ };
79
+
80
+ const getTableRows = () => {
81
+ const rows: React.ReactElement[] = [];
82
+
83
+ subscriptions.forEach((sub: any) => {
84
+ rows.push(<TableRow key={sub.id}>
85
+ <TableCell>{DateHelper.prettyDate(new Date(sub.billing_cycle_anchor * 1000))}</TableCell>
86
+ <TableCell>{getFunds(sub)}</TableCell>
87
+ <TableCell>{Locale.label("donation.recurring.every")} {getInterval(sub)}</TableCell>
88
+ <TableCell className="capitalize">{getPaymentMethod(sub)}</TableCell>
89
+ <TableCell align="right">{getEditOptions(sub)}</TableCell>
90
+ </TableRow>);
91
+ });
92
+ return rows;
93
+ };
94
+
95
+ const getSubscriptionsTable = () => (
96
+ <Table>
97
+ <TableHead>{getTableHeader()}</TableHead>
98
+ <TableBody>{getTableRows()}</TableBody>
99
+ </Table>
100
+ );
101
+
102
+ React.useEffect(loadData, []); //eslint-disable-line
103
+
104
+ if (!subscriptions.length) return null;
105
+ if (mode === "display") {
106
+ return (
107
+ <DisplayBox data-testid="recurring-donations" headerIcon="restart_alt" headerText="Recurring Donations">
108
+ {getSubscriptionsTable()}
109
+ </DisplayBox>
110
+ );
111
+ }
112
+ if (mode === "edit" && editSubscription) {
113
+ return (
114
+ <RecurringDonationsEdit customerId={props.customerId} paymentMethods={props.paymentMethods} editSubscription={editSubscription} subscriptionUpdated={handleUpdate} />
115
+ );
116
+ }
117
+ };
@@ -0,0 +1,96 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { ApiHelper, Locale } from "../../helpers";
5
+ import { InputBox } from "../../components";
6
+ import { StripePaymentMethod, SubscriptionInterface } from "@churchapps/helpers";
7
+ import { FormControl, Grid, InputLabel, MenuItem, Select, TextField } from "@mui/material";
8
+ import type { SelectChangeEvent } from "@mui/material";
9
+ import { DonationHelper } from "../../helpers";
10
+
11
+ interface Props { subscriptionUpdated: (message?: string) => void, customerId: string, paymentMethods: StripePaymentMethod[], editSubscription: SubscriptionInterface };
12
+
13
+ export const RecurringDonationsEdit: React.FC<Props> = (props) => {
14
+ const [editSubscription, setEditSubscription] = React.useState<SubscriptionInterface>(props.editSubscription);
15
+ const [interval, setInterval] = React.useState("one_month");
16
+
17
+ const handleCancel = () => { props.subscriptionUpdated(); };
18
+ const handleSave = () => {
19
+ const sub = { ...editSubscription } as SubscriptionInterface;
20
+ const pmFound = props.paymentMethods.find((pm: StripePaymentMethod) => pm.id === sub.id);
21
+ if (!pmFound) {
22
+ const pm = props.paymentMethods[0];
23
+ sub.default_payment_method = pm.type === "card" ? pm.id : null;
24
+ sub.default_source = pm.type === "bank" ? pm.id : null;
25
+ }
26
+ ApiHelper.post("/subscriptions", [sub], "GivingApi").then(() => props.subscriptionUpdated(Locale.label("donation.donationForm.recurringUpdated")));
27
+ };
28
+
29
+ const handleDelete = () => {
30
+ const conf = window.confirm(Locale.label("donation.donationForm.confirmDelete"));
31
+ if (!conf) return;
32
+ const promises = [];
33
+ promises.push(ApiHelper.delete("/subscriptions/" + props.editSubscription.id, "GivingApi"));
34
+ promises.push(ApiHelper.delete("/subscriptionfunds/subscription/" + props.editSubscription.id, "GivingApi"));
35
+ Promise.all(promises).then(() => props.subscriptionUpdated(Locale.label("donation.donationForm.cancelled")));
36
+ };
37
+
38
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | SelectChangeEvent<string>) => {
39
+ const sub = { ...editSubscription } as SubscriptionInterface;
40
+ const value = e.target.value;
41
+ switch (e.target.name) {
42
+ case "method":
43
+ const pm = props.paymentMethods.find((pm: StripePaymentMethod) => pm.id === value);
44
+ sub.default_payment_method = pm.type === "card" ? value : null;
45
+ sub.default_source = pm.type === "bank" ? value : null;
46
+ break;
47
+ case "interval":
48
+ setInterval(value);
49
+ const inter = DonationHelper.getInterval(value);
50
+ sub.plan.interval_count = inter.interval_count;
51
+ sub.plan.interval = inter.interval;
52
+ break;
53
+ }
54
+ setEditSubscription(sub);
55
+ };
56
+
57
+ const getFields = () => (
58
+ <>
59
+ <Grid container spacing={3}>
60
+ <Grid size={{ xs: 12, md: 6 }}>
61
+ <FormControl fullWidth>
62
+ <InputLabel>{Locale.label("donation.donationForm.method")}</InputLabel>
63
+ <Select label={Locale.label("donation.donationForm.method")} name="method" aria-label="method" value={editSubscription.default_payment_method || editSubscription.default_source} className="capitalize" onChange={handleChange}>
64
+ {props.paymentMethods.map((paymentMethod: any, i: number) => <MenuItem key={i} value={paymentMethod.id}>{paymentMethod.name} ****{paymentMethod.last4}</MenuItem>)}
65
+ </Select>
66
+ </FormControl>
67
+ </Grid>
68
+ <Grid size={{ xs: 12, md: 6 }}>
69
+ <FormControl fullWidth>
70
+ <InputLabel>{Locale.label("donation.donationForm.frequency")}</InputLabel>
71
+ <Select label={Locale.label("donation.donationForm.frequency")} name="interval" aria-label="interval" value={interval} onChange={handleChange}>
72
+ <MenuItem value="one_week">{Locale.label("donation.donationForm.weekly")}</MenuItem>
73
+ <MenuItem value="two_week">{Locale.label("donation.donationForm.biWeekly")}</MenuItem>
74
+ <MenuItem value="one_month">{Locale.label("donation.donationForm.monthly")}</MenuItem>
75
+ <MenuItem value="three_month">{Locale.label("donation.donationForm.quarterly")}</MenuItem>
76
+ <MenuItem value="one_year">{Locale.label("donation.donationForm.annually")}</MenuItem>
77
+ </Select>
78
+ </FormControl>
79
+ </Grid>
80
+ </Grid>
81
+ </>
82
+ );
83
+
84
+ React.useEffect(() => {
85
+ if (props.editSubscription) {
86
+ const keyName = DonationHelper.getIntervalKeyName(props.editSubscription.plan.interval_count, props.editSubscription.plan.interval);
87
+ setInterval(keyName);
88
+ }
89
+ }, [props.editSubscription]);
90
+
91
+ return (
92
+ <InputBox aria-label="person-details-box" headerIcon="person" headerText={Locale.label("donation.donationForm.editRecurring")} ariaLabelSave="save-button" ariaLabelDelete="delete-button" cancelFunction={handleCancel} deleteFunction={handleDelete} saveFunction={handleSave}>
93
+ {getFields()}
94
+ </InputBox>
95
+ );
96
+ };
@@ -0,0 +1,8 @@
1
+ export { BankForm } from "./BankForm";
2
+ export { CardForm } from "./CardForm";
3
+ export { DonationForm } from "./DonationForm";
4
+ export { FundDonation } from "./FundDonation";
5
+ export { FundDonations } from "./FundDonations";
6
+ export { PaymentMethods } from "./PaymentMethods";
7
+ export { RecurringDonations } from "./RecurringDonations";
8
+ export { RecurringDonationsEdit } from "./RecurringDonationsEdit";
@@ -0,0 +1,2 @@
1
+ export * from "./components";
2
+ export { DonationPreviewModal } from "./modals/DonationPreviewModal";
@@ -0,0 +1,70 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { DateHelper, CurrencyHelper, Locale } from "../../helpers";
5
+ import { StripeDonationInterface } from "@churchapps/helpers";
6
+ import {
7
+ Table, TableBody, TableRow, TableCell, Dialog, DialogTitle, DialogContent, DialogActions, Button
8
+ } from "@mui/material";
9
+
10
+ interface Props {
11
+ show: boolean;
12
+ onHide: () => void;
13
+ handleDonate: (message: string) => void;
14
+ donation: StripeDonationInterface;
15
+ donationType: string;
16
+ paymentMethodName: string;
17
+ funds: any;
18
+ payFee: number;
19
+ }
20
+
21
+ export const DonationPreviewModal: React.FC<Props> = (props) => {
22
+ const donationType: any = { once: "One-time Donation", recurring: "Recurring Donation" };
23
+ const [isLoading, setLoading] = React.useState<boolean>(false);
24
+
25
+ const handleClick = () => {
26
+ setLoading(true);
27
+ let message = "Thank you for your donation.";
28
+ if (props.donationType === "recurring") message = "Recurring donation created. " + message;
29
+ props.handleDonate(message);
30
+ };
31
+
32
+ const formatInterval = () => {
33
+ const count = props.donation.interval.interval_count;
34
+ const interval = props.donation.interval.interval;
35
+ const result = `${count} ${interval}`;
36
+ return count > 1 ? result + "s" : result;
37
+ };
38
+
39
+ return (
40
+ <Dialog open={props.show} {...props}>
41
+ <DialogTitle>Donation Preview</DialogTitle>
42
+ <DialogContent>
43
+ <Table>
44
+ <TableBody>
45
+ <TableRow><TableCell>{Locale.label("person.name")}:</TableCell><TableCell>{props.donation.person.name}</TableCell></TableRow>
46
+ <TableRow><TableCell>{Locale.label("donation.preview.method")}:</TableCell><TableCell className="capitalize">{props.paymentMethodName}</TableCell></TableRow>
47
+ <TableRow><TableCell>{Locale.label("donation.preview.type")}:</TableCell><TableCell>{donationType[props.donationType]}</TableCell></TableRow>
48
+ {props.donationType === "once"
49
+ && <TableRow><TableCell>{Locale.label("donation.preview.date")}:</TableCell><TableCell>{DateHelper.formatHtml5Date(new Date(props.donation.billing_cycle_anchor))}</TableCell></TableRow>
50
+ }
51
+ <TableRow><TableCell>{Locale.label("donation.preview.weekly")}:</TableCell><TableCell>{props.donation.notes}</TableCell></TableRow>
52
+ {props.donationType === "recurring"
53
+ && <>
54
+ <TableRow><TableCell>{Locale.label("donation.preview.startingOn")}:</TableCell><TableCell>{DateHelper.formatHtml5Date(new Date(props.donation.billing_cycle_anchor))}</TableCell></TableRow>
55
+ <TableRow><TableCell>{Locale.label("donation.preview.every")}:</TableCell><TableCell className="capitalize">{formatInterval()}</TableCell></TableRow>
56
+ </>
57
+ }
58
+ <TableRow><TableCell>{Locale.label("donation.preview.funds")}:</TableCell><TableCell>{props.donation.funds.map((fund: any, i: number) => <p key={i}>{CurrencyHelper.formatCurrency(fund.amount)} - {fund.name}</p>)}</TableCell></TableRow>
59
+ {props.payFee > 0 && <TableRow><TableCell>{Locale.label("donation.preview.fee")}:</TableCell><TableCell>{CurrencyHelper.formatCurrency(props.payFee)}</TableCell></TableRow>}
60
+ <TableRow><TableCell>{Locale.label("donation.preview.total")}:</TableCell><TableCell><h4>{CurrencyHelper.formatCurrency(props.donation.amount)}</h4></TableCell></TableRow>
61
+ </TableBody>
62
+ </Table>
63
+ </DialogContent>
64
+ <DialogActions>
65
+ <Button onClick={props.onHide} variant="outlined" aria-label="cancel-button">{Locale.label("donation.common.cancel")}</Button>
66
+ <Button onClick={handleClick} variant="contained" aria-label="donate-button" disabled={isLoading}>{Locale.label("donation.preview.donate")}</Button>
67
+ </DialogActions>
68
+ </Dialog>
69
+ );
70
+ };
package/src/index.ts CHANGED
@@ -3,3 +3,4 @@ export * from "./components";
3
3
  export * from "@churchapps/helpers";
4
4
  export * from "./pageComponents";
5
5
  export * from "./hooks";
6
+ export * from "./donationComponents";