@churchapps/apphelper 0.1.8 → 0.1.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 (198) hide show
  1. package/.eslintignore +3 -3
  2. package/.eslintrc.json +22 -22
  3. package/LICENSE +21 -21
  4. package/README.md +24 -24
  5. package/dist/components/gallery/GalleryModal.d.ts.map +1 -1
  6. package/dist/components/gallery/GalleryModal.js +13 -2
  7. package/dist/components/gallery/GalleryModal.js.map +1 -1
  8. package/dist/components/markdownEditor/editor.css +787 -787
  9. package/dist/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  10. package/dist/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  11. package/dist/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  12. package/dist/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  13. package/dist/components/markdownEditor/images/icons/code.svg +2 -2
  14. package/dist/components/markdownEditor/images/icons/journal-code.svg +4 -4
  15. package/dist/components/markdownEditor/images/icons/journal-text.svg +4 -4
  16. package/dist/components/markdownEditor/images/icons/justify.svg +2 -2
  17. package/dist/components/markdownEditor/images/icons/link.svg +3 -3
  18. package/dist/components/markdownEditor/images/icons/list-ol.svg +3 -3
  19. package/dist/components/markdownEditor/images/icons/list-ul.svg +2 -2
  20. package/dist/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  21. package/dist/components/markdownEditor/images/icons/text-center.svg +2 -2
  22. package/dist/components/markdownEditor/images/icons/text-left.svg +2 -2
  23. package/dist/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  24. package/dist/components/markdownEditor/images/icons/text-right.svg +2 -2
  25. package/dist/components/markdownEditor/images/icons/type-bold.svg +2 -2
  26. package/dist/components/markdownEditor/images/icons/type-h1.svg +2 -2
  27. package/dist/components/markdownEditor/images/icons/type-h2.svg +2 -2
  28. package/dist/components/markdownEditor/images/icons/type-h3.svg +2 -2
  29. package/dist/components/markdownEditor/images/icons/type-h4.svg +12 -12
  30. package/dist/components/markdownEditor/images/icons/type-italic.svg +2 -2
  31. package/dist/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  32. package/dist/components/markdownEditor/images/icons/type-underline.svg +2 -2
  33. package/dist/helpers/SlugHelper.d.ts +5 -0
  34. package/dist/helpers/SlugHelper.d.ts.map +1 -0
  35. package/dist/helpers/SlugHelper.js +40 -0
  36. package/dist/helpers/SlugHelper.js.map +1 -0
  37. package/dist/helpers/index.d.ts +1 -0
  38. package/dist/helpers/index.d.ts.map +1 -1
  39. package/dist/helpers/index.js +3 -1
  40. package/dist/helpers/index.js.map +1 -1
  41. package/package.json +88 -86
  42. package/src/components/CreatePerson.tsx +80 -80
  43. package/src/components/DisplayBox.tsx +68 -68
  44. package/src/components/ErrorMessages.tsx +26 -26
  45. package/src/components/ExportLink.tsx +67 -67
  46. package/src/components/FloatingSupport.tsx +16 -16
  47. package/src/components/FormSubmissionEdit.tsx +120 -120
  48. package/src/components/HelpIcon.tsx +10 -10
  49. package/src/components/ImageEditor.tsx +126 -126
  50. package/src/components/InputBox.tsx +73 -73
  51. package/src/components/Loading.tsx +29 -29
  52. package/src/components/PersonAdd.tsx +75 -75
  53. package/src/components/QuestionEdit.tsx +63 -63
  54. package/src/components/SmallButton.tsx +39 -39
  55. package/src/components/SupportModal.tsx +26 -26
  56. package/src/components/TabPanel.tsx +34 -34
  57. package/src/components/gallery/GalleryModal.tsx +119 -102
  58. package/src/components/gallery/StockPhotos.tsx +74 -74
  59. package/src/components/gallery/index.ts +1 -1
  60. package/src/components/iconPicker/IconNamesList.ts +2240 -2240
  61. package/src/components/iconPicker/IconPicker.tsx +153 -153
  62. package/src/components/index.tsx +24 -24
  63. package/src/components/markdownEditor/Editor.tsx +132 -132
  64. package/src/components/markdownEditor/MarkdownEditor.tsx +16 -16
  65. package/src/components/markdownEditor/MarkdownModal.tsx +46 -46
  66. package/src/components/markdownEditor/MarkdownPreview.tsx +14 -14
  67. package/src/components/markdownEditor/editor.css +787 -787
  68. package/src/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  69. package/src/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  70. package/src/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  71. package/src/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  72. package/src/components/markdownEditor/images/icons/code.svg +2 -2
  73. package/src/components/markdownEditor/images/icons/journal-code.svg +4 -4
  74. package/src/components/markdownEditor/images/icons/journal-text.svg +4 -4
  75. package/src/components/markdownEditor/images/icons/justify.svg +2 -2
  76. package/src/components/markdownEditor/images/icons/link.svg +3 -3
  77. package/src/components/markdownEditor/images/icons/list-ol.svg +3 -3
  78. package/src/components/markdownEditor/images/icons/list-ul.svg +2 -2
  79. package/src/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  80. package/src/components/markdownEditor/images/icons/text-center.svg +2 -2
  81. package/src/components/markdownEditor/images/icons/text-left.svg +2 -2
  82. package/src/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  83. package/src/components/markdownEditor/images/icons/text-right.svg +2 -2
  84. package/src/components/markdownEditor/images/icons/type-bold.svg +2 -2
  85. package/src/components/markdownEditor/images/icons/type-h1.svg +2 -2
  86. package/src/components/markdownEditor/images/icons/type-h2.svg +2 -2
  87. package/src/components/markdownEditor/images/icons/type-h3.svg +2 -2
  88. package/src/components/markdownEditor/images/icons/type-h4.svg +12 -12
  89. package/src/components/markdownEditor/images/icons/type-italic.svg +2 -2
  90. package/src/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  91. package/src/components/markdownEditor/images/icons/type-underline.svg +2 -2
  92. package/src/components/markdownEditor/index.ts +2 -2
  93. package/src/components/markdownEditor/plugins/AutoLinkPlugin.tsx +35 -35
  94. package/src/components/markdownEditor/plugins/ControlledEditorPlugin.tsx +24 -24
  95. package/src/components/markdownEditor/plugins/ListMaxIndentLevelPlugin.tsx +68 -68
  96. package/src/components/markdownEditor/plugins/MarkdownTransformers.ts +106 -106
  97. package/src/components/markdownEditor/plugins/ReadOnlyPlugin.tsx +15 -15
  98. package/src/components/markdownEditor/plugins/ToolbarPlugin.tsx +401 -401
  99. package/src/components/markdownEditor/plugins/customLink/CustomLinkNode.tsx +224 -224
  100. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodePlugin.tsx +32 -32
  101. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodeTransformer.tsx +102 -102
  102. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.tsx +243 -243
  103. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.types.ts +11 -11
  104. package/src/components/markdownEditor/plugins/emoji/EmojiNode.tsx +95 -95
  105. package/src/components/markdownEditor/plugins/emoji/EmojiNodeTransform.ts +41 -41
  106. package/src/components/markdownEditor/plugins/emoji/EmojiPickerPlugin.tsx +152 -152
  107. package/src/components/markdownEditor/plugins/emoji/EmojisPlugin.tsx +65 -65
  108. package/src/components/markdownEditor/plugins/index.ts +6 -6
  109. package/src/components/markdownEditor/theme.ts +65 -65
  110. package/src/components/notes/AddNote.tsx +90 -90
  111. package/src/components/notes/Conversation.tsx +82 -82
  112. package/src/components/notes/Conversations.tsx +58 -58
  113. package/src/components/notes/NewConversation.tsx +78 -78
  114. package/src/components/notes/Note.tsx +44 -44
  115. package/src/components/notes/Notes.tsx +69 -69
  116. package/src/components/notes/index.ts +5 -5
  117. package/src/components/reporting/ChartReport.tsx +98 -98
  118. package/src/components/reporting/ReportFilter.tsx +54 -54
  119. package/src/components/reporting/ReportFilterField.tsx +160 -160
  120. package/src/components/reporting/ReportOutput.tsx +79 -79
  121. package/src/components/reporting/ReportWithFilter.tsx +70 -70
  122. package/src/components/reporting/TableReport.tsx +57 -57
  123. package/src/components/reporting/TreeReport.tsx +111 -111
  124. package/src/components/reporting/index.ts +4 -4
  125. package/src/components/wrapper/AppList.tsx +20 -20
  126. package/src/components/wrapper/ChurchList.tsx +22 -22
  127. package/src/components/wrapper/Drawers.tsx +60 -60
  128. package/src/components/wrapper/NavItem.tsx +41 -41
  129. package/src/components/wrapper/NewPrivateMessage.tsx +103 -103
  130. package/src/components/wrapper/NotificationMenu.tsx +96 -96
  131. package/src/components/wrapper/Notifications.tsx +53 -53
  132. package/src/components/wrapper/PrivateMessageDetails.tsx +24 -24
  133. package/src/components/wrapper/PrivateMessages.tsx +92 -92
  134. package/src/components/wrapper/SiteWrapper.tsx +99 -99
  135. package/src/components/wrapper/TabPanel.tsx +30 -30
  136. package/src/components/wrapper/UserMenu.tsx +106 -106
  137. package/src/components/wrapper/index.tsx +5 -5
  138. package/src/donationComponents/DonationPage.tsx +136 -136
  139. package/src/donationComponents/components/BankForm.tsx +159 -159
  140. package/src/donationComponents/components/CardForm.tsx +104 -104
  141. package/src/donationComponents/components/DonationForm.tsx +235 -235
  142. package/src/donationComponents/components/FundDonation.tsx +49 -49
  143. package/src/donationComponents/components/FundDonations.tsx +39 -39
  144. package/src/donationComponents/components/NonAuthDonation.tsx +31 -31
  145. package/src/donationComponents/components/NonAuthDonationInner.tsx +259 -259
  146. package/src/donationComponents/components/PaymentMethods.tsx +135 -135
  147. package/src/donationComponents/components/RecurringDonations.tsx +121 -121
  148. package/src/donationComponents/components/RecurringDonationsEdit.tsx +93 -93
  149. package/src/donationComponents/components/index.tsx +9 -9
  150. package/src/donationComponents/index.ts +3 -3
  151. package/src/donationComponents/modals/DonationPreviewModal.tsx +66 -66
  152. package/src/helpers/AnalyticsHelper.ts +33 -33
  153. package/src/helpers/ApiHelper.ts +125 -125
  154. package/src/helpers/AppearanceHelper.ts +69 -69
  155. package/src/helpers/ArrayHelper.ts +81 -81
  156. package/src/helpers/CommonEnvironmentHelper.ts +80 -80
  157. package/src/helpers/CurrencyHelper.ts +10 -10
  158. package/src/helpers/DateHelper.ts +109 -109
  159. package/src/helpers/DonationHelper.ts +26 -26
  160. package/src/helpers/ErrorHelper.ts +36 -36
  161. package/src/helpers/EventHelper.ts +52 -52
  162. package/src/helpers/FileHelper.ts +31 -31
  163. package/src/helpers/PersonHelper.ts +60 -60
  164. package/src/helpers/SlugHelper.ts +38 -0
  165. package/src/helpers/SocketHelper.ts +78 -78
  166. package/src/helpers/Themes.ts +14 -14
  167. package/src/helpers/UniqueIdHelper.ts +36 -36
  168. package/src/helpers/UserHelper.ts +59 -59
  169. package/src/helpers/createEmotionCache.ts +17 -17
  170. package/src/helpers/index.ts +19 -18
  171. package/src/hooks/index.ts +1 -1
  172. package/src/hooks/useMountedState.ts +16 -16
  173. package/src/index.ts +6 -6
  174. package/src/interfaces/Access.ts +24 -24
  175. package/src/interfaces/Attendance.ts +8 -8
  176. package/src/interfaces/Content.ts +10 -10
  177. package/src/interfaces/Doing.ts +24 -24
  178. package/src/interfaces/Donation.ts +45 -45
  179. package/src/interfaces/Error.ts +17 -17
  180. package/src/interfaces/Membership.ts +51 -51
  181. package/src/interfaces/Messaging.ts +11 -11
  182. package/src/interfaces/Permissions.ts +68 -68
  183. package/src/interfaces/Reporting.ts +7 -7
  184. package/src/interfaces/UserContextInterface.ts +13 -13
  185. package/src/interfaces/index.ts +13 -13
  186. package/src/pageComponents/LoginPage.tsx +244 -244
  187. package/src/pageComponents/LogoutPage.tsx +28 -28
  188. package/src/pageComponents/components/Forgot.tsx +79 -79
  189. package/src/pageComponents/components/Login.tsx +54 -54
  190. package/src/pageComponents/components/LoginSetPassword.tsx +63 -63
  191. package/src/pageComponents/components/Register.tsx +107 -107
  192. package/src/pageComponents/components/SelectChurchModal.tsx +41 -41
  193. package/src/pageComponents/components/SelectChurchRegister.tsx +88 -88
  194. package/src/pageComponents/components/SelectChurchSearch.tsx +69 -69
  195. package/src/pageComponents/components/SelectableChurch.tsx +38 -38
  196. package/src/pageComponents/index.ts +3 -3
  197. package/tsconfig.json +34 -34
  198. package/tslint.json +14 -14
@@ -1,73 +1,73 @@
1
- import React from "react";
2
- import { Paper, Box, Typography, Stack, styled, Button, Icon, PaperProps } from "@mui/material";
3
- import { HelpIcon } from "./HelpIcon";
4
-
5
- interface Props {
6
- id?: string;
7
- children?: React.ReactNode;
8
- headerIcon?: string;
9
- headerText?: string;
10
- help?: string;
11
- saveText?: string;
12
- headerActionContent?: React.ReactNode;
13
- cancelFunction?: () => void;
14
- deleteFunction?: () => void;
15
- saveFunction: () => void;
16
- "data-cy"?: string;
17
- className?: string;
18
- isSubmitting?: boolean;
19
- ariaLabelDelete?: string;
20
- ariaLabelSave?: string;
21
- saveButtonType?: "submit" | "button";
22
- mainContainerCssProps?: PaperProps;
23
- }
24
-
25
- const CustomContextBox = styled(Box)({
26
- marginTop: 10,
27
- overflowX: "hidden",
28
- "& p": { color: "#666" },
29
- "& label": { color: "#999" },
30
- "& ul": { paddingLeft: 15 },
31
- "& li": {
32
- marginBottom: 10,
33
- "& i": { marginRight: 5 }
34
- },
35
- "& td": {
36
- "& i": { marginRight: 5 }
37
- }
38
- })
39
-
40
- export function InputBox({ mainContainerCssProps = {}, ...props }: Props) {
41
- let buttons = [];
42
- if (props.cancelFunction) buttons.push(<Button key="cancel" onClick={props.cancelFunction} color="warning" sx={{ "&:focus": { outline: "none" } }}>Cancel</Button>);
43
- if (props.deleteFunction) buttons.push(<Button key="delete" id="delete" variant="outlined" aria-label={props.ariaLabelDelete} onClick={props.deleteFunction} color="error" sx={{ "&:focus": { outline: "none" } }}>Delete</Button>);
44
- if (props.saveFunction) buttons.push(<Button key="save" type={props.saveButtonType || "button"} variant="contained" disableElevation aria-label={props.ariaLabelSave} onClick={props.saveFunction} disabled={props.isSubmitting} sx={{ "&:focus": { outline: "none" } }}>{props.saveText || "save"}</Button>);
45
-
46
- let classNames = ["inputBox"];
47
- if (props.className) {
48
- classNames.push(props.className);
49
- }
50
-
51
- return (
52
- <Paper id={props.id} sx={{ padding: 2, marginBottom: 4 }} data-cy={props["data-cy"]} {...mainContainerCssProps}>
53
- {props.help && <HelpIcon article={props.help} />}
54
- <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", position: "relative" }} data-cy="header">
55
- <Box sx={{ display: "flex", alignItems: "center" }}>
56
- {props.headerIcon && <Icon sx={{ color: "#1976d2" }}>{props.headerIcon}</Icon>}
57
- {props.headerText && (
58
- <Typography component="h2" sx={{ display: "inline-block", marginLeft: props.headerIcon ? 1 : 0 }} variant="h6" color="primary">
59
- {props.headerText}
60
- </Typography>
61
- )}
62
- </Box>
63
- <Box>
64
- {props.headerActionContent}
65
- </Box>
66
- </Box>
67
- <CustomContextBox>{props.children}</CustomContextBox>
68
- <Stack direction="row" sx={{ marginTop: 1 }} spacing={1} justifyContent="end">
69
- {buttons}
70
- </Stack>
71
- </Paper>
72
- );
73
- }
1
+ import React from "react";
2
+ import { Paper, Box, Typography, Stack, styled, Button, Icon, PaperProps } from "@mui/material";
3
+ import { HelpIcon } from "./HelpIcon";
4
+
5
+ interface Props {
6
+ id?: string;
7
+ children?: React.ReactNode;
8
+ headerIcon?: string;
9
+ headerText?: string;
10
+ help?: string;
11
+ saveText?: string;
12
+ headerActionContent?: React.ReactNode;
13
+ cancelFunction?: () => void;
14
+ deleteFunction?: () => void;
15
+ saveFunction: () => void;
16
+ "data-cy"?: string;
17
+ className?: string;
18
+ isSubmitting?: boolean;
19
+ ariaLabelDelete?: string;
20
+ ariaLabelSave?: string;
21
+ saveButtonType?: "submit" | "button";
22
+ mainContainerCssProps?: PaperProps;
23
+ }
24
+
25
+ const CustomContextBox = styled(Box)({
26
+ marginTop: 10,
27
+ overflowX: "hidden",
28
+ "& p": { color: "#666" },
29
+ "& label": { color: "#999" },
30
+ "& ul": { paddingLeft: 15 },
31
+ "& li": {
32
+ marginBottom: 10,
33
+ "& i": { marginRight: 5 }
34
+ },
35
+ "& td": {
36
+ "& i": { marginRight: 5 }
37
+ }
38
+ })
39
+
40
+ export function InputBox({ mainContainerCssProps = {}, ...props }: Props) {
41
+ let buttons = [];
42
+ if (props.cancelFunction) buttons.push(<Button key="cancel" onClick={props.cancelFunction} color="warning" sx={{ "&:focus": { outline: "none" } }}>Cancel</Button>);
43
+ if (props.deleteFunction) buttons.push(<Button key="delete" id="delete" variant="outlined" aria-label={props.ariaLabelDelete} onClick={props.deleteFunction} color="error" sx={{ "&:focus": { outline: "none" } }}>Delete</Button>);
44
+ if (props.saveFunction) buttons.push(<Button key="save" type={props.saveButtonType || "button"} variant="contained" disableElevation aria-label={props.ariaLabelSave} onClick={props.saveFunction} disabled={props.isSubmitting} sx={{ "&:focus": { outline: "none" } }}>{props.saveText || "save"}</Button>);
45
+
46
+ let classNames = ["inputBox"];
47
+ if (props.className) {
48
+ classNames.push(props.className);
49
+ }
50
+
51
+ return (
52
+ <Paper id={props.id} sx={{ padding: 2, marginBottom: 4 }} data-cy={props["data-cy"]} {...mainContainerCssProps}>
53
+ {props.help && <HelpIcon article={props.help} />}
54
+ <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", position: "relative" }} data-cy="header">
55
+ <Box sx={{ display: "flex", alignItems: "center" }}>
56
+ {props.headerIcon && <Icon sx={{ color: "#1976d2" }}>{props.headerIcon}</Icon>}
57
+ {props.headerText && (
58
+ <Typography component="h2" sx={{ display: "inline-block", marginLeft: props.headerIcon ? 1 : 0 }} variant="h6" color="primary">
59
+ {props.headerText}
60
+ </Typography>
61
+ )}
62
+ </Box>
63
+ <Box>
64
+ {props.headerActionContent}
65
+ </Box>
66
+ </Box>
67
+ <CustomContextBox>{props.children}</CustomContextBox>
68
+ <Stack direction="row" sx={{ marginTop: 1 }} spacing={1} justifyContent="end">
69
+ {buttons}
70
+ </Stack>
71
+ </Paper>
72
+ );
73
+ }
@@ -1,29 +1,29 @@
1
- import React from "react";
2
- import { Dots } from "react-activity";
3
- import "react-activity/dist/library.css";
4
-
5
- interface Props { size?: "sm" | "md" | "lg", loadingText?: string, color?: string }
6
-
7
- export const Loading: React.FC<Props> = (props) => {
8
-
9
- const getContents = () => {
10
- const text = (props.loadingText) ? props.loadingText : "Loading"
11
- const color = (props.color) ? props.color : "#222"
12
- let result = <><Dots speed={0.8} animating={true} size={32} color={color} /><p style={{ color: color }}>{text}</p></>
13
- switch (props.size) {
14
- case "sm":
15
- result = <><Dots speed={0.8} animating={true} size={20} color={color} /><p style={{ fontSize: 12, color: color }}>{text}</p></>
16
- break;
17
- case "lg":
18
- result = <><Dots speed={0.8} animating={true} size={48} color={color} /><p style={{ fontSize: 30, color: color }}>{text}</p></>
19
- break;
20
- }
21
- return result;
22
- }
23
-
24
- return (
25
- <div style={{ textAlign: "center", fontFamily: "Roboto" }}>
26
- {getContents()}
27
- </div>
28
- )
29
- }
1
+ import React from "react";
2
+ import { Dots } from "react-activity";
3
+ import "react-activity/dist/library.css";
4
+
5
+ interface Props { size?: "sm" | "md" | "lg", loadingText?: string, color?: string }
6
+
7
+ export const Loading: React.FC<Props> = (props) => {
8
+
9
+ const getContents = () => {
10
+ const text = (props.loadingText) ? props.loadingText : "Loading"
11
+ const color = (props.color) ? props.color : "#222"
12
+ let result = <><Dots speed={0.8} animating={true} size={32} color={color} /><p style={{ color: color }}>{text}</p></>
13
+ switch (props.size) {
14
+ case "sm":
15
+ result = <><Dots speed={0.8} animating={true} size={20} color={color} /><p style={{ fontSize: 12, color: color }}>{text}</p></>
16
+ break;
17
+ case "lg":
18
+ result = <><Dots speed={0.8} animating={true} size={48} color={color} /><p style={{ fontSize: 30, color: color }}>{text}</p></>
19
+ break;
20
+ }
21
+ return result;
22
+ }
23
+
24
+ return (
25
+ <div style={{ textAlign: "center", fontFamily: "Roboto" }}>
26
+ {getContents()}
27
+ </div>
28
+ )
29
+ }
@@ -1,75 +1,75 @@
1
- import React, { useState } from "react";
2
- import { ApiHelper } from "../helpers";
3
- import { PersonInterface } from "../interfaces"
4
- import { TextField, Button, Table, TableBody, TableRow, TableCell } from "@mui/material";
5
- import { SmallButton } from "./SmallButton";
6
- import { CreatePerson } from "./CreatePerson";
7
-
8
- interface Props {
9
- addFunction: (person: PersonInterface) => void;
10
- person?: PersonInterface;
11
- getPhotoUrl: (person: PersonInterface) => string;
12
- searchClicked?: () => void;
13
- filterList?: string[];
14
- includeEmail?: boolean;
15
- actionLabel?: string;
16
- showCreatePersonOnNotFound?: boolean;
17
- }
18
-
19
- export const PersonAdd: React.FC<Props> = ({ addFunction, getPhotoUrl, searchClicked, filterList = [], includeEmail = false, actionLabel, showCreatePersonOnNotFound = false }) => {
20
- const [searchResults, setSearchResults] = useState<PersonInterface[]>([]);
21
- const [searchText, setSearchText] = useState("");
22
- const [hasSearched, setHasSearched] = useState<boolean>(false);
23
-
24
- const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setHasSearched(false); setSearchText(e.currentTarget.value); }
25
- const handleKeyDown = (e: React.KeyboardEvent<any>) => { if (e.key === "Enter") { e.preventDefault(); handleSearch(null); } }
26
-
27
- const handleSearch = (e: React.MouseEvent) => {
28
- if (e !== null) e.preventDefault();
29
- let term = searchText.trim();
30
- ApiHelper.post("/people/search", { term: term }, "MembershipApi")
31
- .then((data: PersonInterface[]) => {
32
- setHasSearched(true);
33
- const filteredResult = data.filter(s => !filterList.includes(s.id))
34
- setSearchResults(filteredResult);
35
- if (searchClicked) {
36
- searchClicked();
37
- }
38
- });
39
- }
40
- const handleAdd = (person: PersonInterface) => {
41
- let sr: PersonInterface[] = [...searchResults];
42
- const idx = sr.indexOf(person);
43
- sr.splice(idx, 1);
44
- setSearchResults(sr);
45
- addFunction(person);
46
- }
47
-
48
- //<button className="text-success no-default-style" aria-label="addPerson" data-index={i} onClick={handleAdd}><Icon>person</Icon> Add</button>
49
- let rows = [];
50
- for (let i = 0; i < searchResults.length; i++) {
51
- const sr = searchResults[i];
52
-
53
- rows.push(
54
- <TableRow key={sr.id}>
55
- <TableCell><img src={getPhotoUrl(sr)} alt="avatar" /></TableCell>
56
- <TableCell>{sr.name.display}{includeEmail && (<><br /><i style={{ color: "#999" }}>{sr.contactInfo.email}</i></>)}</TableCell>
57
- <TableCell>
58
- <SmallButton color="success" icon="person" text={actionLabel || "Add"} ariaLabel="addPerson" onClick={() => handleAdd(sr)} />
59
- </TableCell>
60
- </TableRow>
61
- );
62
- }
63
-
64
- return (
65
- <>
66
- <TextField fullWidth name="personAddText" label="Person" value={searchText} onChange={handleChange} onKeyDown={handleKeyDown}
67
- InputProps={{ endAdornment: <Button variant="contained" id="searchButton" data-cy="search-button" onClick={handleSearch}>Search</Button> }}
68
- />
69
- {showCreatePersonOnNotFound && hasSearched && searchText && searchResults.length === 0 && (
70
- <CreatePerson navigateOnCreate={false} onCreate={person => { setSearchText(""); setSearchResults([person]) }} />
71
- )}
72
- <Table size="small" id="householdMemberAddTable"><TableBody>{rows}</TableBody></Table>
73
- </>
74
- );
75
- }
1
+ import React, { useState } from "react";
2
+ import { ApiHelper } from "../helpers";
3
+ import { PersonInterface } from "../interfaces"
4
+ import { TextField, Button, Table, TableBody, TableRow, TableCell } from "@mui/material";
5
+ import { SmallButton } from "./SmallButton";
6
+ import { CreatePerson } from "./CreatePerson";
7
+
8
+ interface Props {
9
+ addFunction: (person: PersonInterface) => void;
10
+ person?: PersonInterface;
11
+ getPhotoUrl: (person: PersonInterface) => string;
12
+ searchClicked?: () => void;
13
+ filterList?: string[];
14
+ includeEmail?: boolean;
15
+ actionLabel?: string;
16
+ showCreatePersonOnNotFound?: boolean;
17
+ }
18
+
19
+ export const PersonAdd: React.FC<Props> = ({ addFunction, getPhotoUrl, searchClicked, filterList = [], includeEmail = false, actionLabel, showCreatePersonOnNotFound = false }) => {
20
+ const [searchResults, setSearchResults] = useState<PersonInterface[]>([]);
21
+ const [searchText, setSearchText] = useState("");
22
+ const [hasSearched, setHasSearched] = useState<boolean>(false);
23
+
24
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setHasSearched(false); setSearchText(e.currentTarget.value); }
25
+ const handleKeyDown = (e: React.KeyboardEvent<any>) => { if (e.key === "Enter") { e.preventDefault(); handleSearch(null); } }
26
+
27
+ const handleSearch = (e: React.MouseEvent) => {
28
+ if (e !== null) e.preventDefault();
29
+ let term = searchText.trim();
30
+ ApiHelper.post("/people/search", { term: term }, "MembershipApi")
31
+ .then((data: PersonInterface[]) => {
32
+ setHasSearched(true);
33
+ const filteredResult = data.filter(s => !filterList.includes(s.id))
34
+ setSearchResults(filteredResult);
35
+ if (searchClicked) {
36
+ searchClicked();
37
+ }
38
+ });
39
+ }
40
+ const handleAdd = (person: PersonInterface) => {
41
+ let sr: PersonInterface[] = [...searchResults];
42
+ const idx = sr.indexOf(person);
43
+ sr.splice(idx, 1);
44
+ setSearchResults(sr);
45
+ addFunction(person);
46
+ }
47
+
48
+ //<button className="text-success no-default-style" aria-label="addPerson" data-index={i} onClick={handleAdd}><Icon>person</Icon> Add</button>
49
+ let rows = [];
50
+ for (let i = 0; i < searchResults.length; i++) {
51
+ const sr = searchResults[i];
52
+
53
+ rows.push(
54
+ <TableRow key={sr.id}>
55
+ <TableCell><img src={getPhotoUrl(sr)} alt="avatar" /></TableCell>
56
+ <TableCell>{sr.name.display}{includeEmail && (<><br /><i style={{ color: "#999" }}>{sr.contactInfo.email}</i></>)}</TableCell>
57
+ <TableCell>
58
+ <SmallButton color="success" icon="person" text={actionLabel || "Add"} ariaLabel="addPerson" onClick={() => handleAdd(sr)} />
59
+ </TableCell>
60
+ </TableRow>
61
+ );
62
+ }
63
+
64
+ return (
65
+ <>
66
+ <TextField fullWidth name="personAddText" label="Person" value={searchText} onChange={handleChange} onKeyDown={handleKeyDown}
67
+ InputProps={{ endAdornment: <Button variant="contained" id="searchButton" data-cy="search-button" onClick={handleSearch}>Search</Button> }}
68
+ />
69
+ {showCreatePersonOnNotFound && hasSearched && searchText && searchResults.length === 0 && (
70
+ <CreatePerson navigateOnCreate={false} onCreate={person => { setSearchText(""); setSearchResults([person]) }} />
71
+ )}
72
+ <Table size="small" id="householdMemberAddTable"><TableBody>{rows}</TableBody></Table>
73
+ </>
74
+ );
75
+ }
@@ -1,63 +1,63 @@
1
- import React from "react";
2
- import { MuiTelInput } from "mui-tel-input";
3
- import { AnswerInterface, QuestionInterface } from "../interfaces";
4
- import { Select, MenuItem, SelectChangeEvent, FormControl, InputLabel, TextField } from "@mui/material";
5
-
6
- interface Props {
7
- answer: AnswerInterface
8
- question: QuestionInterface,
9
- noBackground?: boolean,
10
- changeFunction: (questionId: string, value: string) => void
11
- }
12
-
13
- export const QuestionEdit: React.FC<Props> = ({noBackground = false, ...props}) => {
14
- const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | SelectChangeEvent<string>) => {
15
- props.changeFunction(props.question.id, e.target.value);
16
- }
17
- let q = props.question;
18
-
19
- if (q.fieldType === "Heading") return <h5>{q.title}</h5>;
20
- else {
21
- let input = null;
22
- let choiceOptions = [];
23
- if (q.choices !== undefined && q.choices !== null) {
24
- for (let i = 0; i < q.choices.length; i++) choiceOptions.push(<MenuItem key={i} value={q.choices[i].value}>{q.choices[i].text}</MenuItem>);
25
- }
26
-
27
- let answerValue = (props.answer === null) ? "" : props.answer.value
28
- switch (q.fieldType) {
29
- case "Textbox": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />; break;
30
- case "Multiple Choice": {
31
- input = (
32
- <FormControl fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}}>
33
- <InputLabel>{q.title}</InputLabel>
34
- <Select fullWidth label={q.title} value={answerValue} onChange={handleChange}>{choiceOptions}</Select>
35
- </FormControl>);
36
- break;
37
- }
38
- case "Yes/No": {
39
- input = (
40
- <FormControl fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}}>
41
- <InputLabel>{q.title}</InputLabel>
42
- <Select fullWidth label={q.title} value={answerValue} onChange={handleChange}>
43
- <MenuItem value="False">No</MenuItem>
44
- <MenuItem value="True">Yes</MenuItem>
45
- </Select>
46
- </FormControl>);
47
- break;
48
- }
49
- case "Whole Number":
50
- case "Decimal":
51
- input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} type="number" InputLabelProps={{shrink: true}} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />;
52
- break;
53
- case "Date": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} type="date" InputLabelProps={{shrink: true}} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />; break;
54
- case "Phone Number": input = <MuiTelInput fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} label={q.title} placeholder="" value={answerValue} onChange={(value) => { props.changeFunction(props.question.id, value); }} defaultCountry="US" focusOnSelectCountry excludedCountries={["TA", "AC"]} />; break;
55
- case "Email": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} type="email" label={q.title} placeholder="john@doe.com" value={answerValue} onChange={handleChange} />; break;
56
- case "Text Area": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} multiline rows={4} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />; break;
57
- default: return null;
58
- }
59
- return input;
60
- }
61
-
62
- }
63
-
1
+ import React from "react";
2
+ import { MuiTelInput } from "mui-tel-input";
3
+ import { AnswerInterface, QuestionInterface } from "../interfaces";
4
+ import { Select, MenuItem, SelectChangeEvent, FormControl, InputLabel, TextField } from "@mui/material";
5
+
6
+ interface Props {
7
+ answer: AnswerInterface
8
+ question: QuestionInterface,
9
+ noBackground?: boolean,
10
+ changeFunction: (questionId: string, value: string) => void
11
+ }
12
+
13
+ export const QuestionEdit: React.FC<Props> = ({noBackground = false, ...props}) => {
14
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | SelectChangeEvent<string>) => {
15
+ props.changeFunction(props.question.id, e.target.value);
16
+ }
17
+ let q = props.question;
18
+
19
+ if (q.fieldType === "Heading") return <h5>{q.title}</h5>;
20
+ else {
21
+ let input = null;
22
+ let choiceOptions = [];
23
+ if (q.choices !== undefined && q.choices !== null) {
24
+ for (let i = 0; i < q.choices.length; i++) choiceOptions.push(<MenuItem key={i} value={q.choices[i].value}>{q.choices[i].text}</MenuItem>);
25
+ }
26
+
27
+ let answerValue = (props.answer === null) ? "" : props.answer.value
28
+ switch (q.fieldType) {
29
+ case "Textbox": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />; break;
30
+ case "Multiple Choice": {
31
+ input = (
32
+ <FormControl fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}}>
33
+ <InputLabel>{q.title}</InputLabel>
34
+ <Select fullWidth label={q.title} value={answerValue} onChange={handleChange}>{choiceOptions}</Select>
35
+ </FormControl>);
36
+ break;
37
+ }
38
+ case "Yes/No": {
39
+ input = (
40
+ <FormControl fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}}>
41
+ <InputLabel>{q.title}</InputLabel>
42
+ <Select fullWidth label={q.title} value={answerValue} onChange={handleChange}>
43
+ <MenuItem value="False">No</MenuItem>
44
+ <MenuItem value="True">Yes</MenuItem>
45
+ </Select>
46
+ </FormControl>);
47
+ break;
48
+ }
49
+ case "Whole Number":
50
+ case "Decimal":
51
+ input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} type="number" InputLabelProps={{shrink: true}} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />;
52
+ break;
53
+ case "Date": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} type="date" InputLabelProps={{shrink: true}} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />; break;
54
+ case "Phone Number": input = <MuiTelInput fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} label={q.title} placeholder="" value={answerValue} onChange={(value) => { props.changeFunction(props.question.id, value); }} defaultCountry="US" focusOnSelectCountry excludedCountries={["TA", "AC"]} />; break;
55
+ case "Email": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} type="email" label={q.title} placeholder="john@doe.com" value={answerValue} onChange={handleChange} />; break;
56
+ case "Text Area": input = <TextField fullWidth style={noBackground ? {backgroundColor: "white", borderRadius: "4px"} : {}} multiline rows={4} label={q.title} placeholder={q.placeholder} value={answerValue} onChange={handleChange} />; break;
57
+ default: return null;
58
+ }
59
+ return input;
60
+ }
61
+
62
+ }
63
+
@@ -1,39 +1,39 @@
1
- import React from "react";
2
- import { Button, Icon, Tooltip } from "@mui/material";
3
- import { Navigate } from "react-router-dom";
4
-
5
- interface Props {
6
- ariaLabel?: string;
7
- text?: string;
8
- icon: string;
9
- color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning";
10
- toolTip?: string;
11
- onClick?: (e: React.MouseEvent) => void;
12
- href?: string;
13
- disabled?: boolean
14
- }
15
-
16
- export const SmallButton = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
17
- const [redirectUrl, setRedirectUrl] = React.useState("");
18
-
19
- const handleClick = (e: React.MouseEvent) => {
20
- e.preventDefault();
21
- if (props.href) setRedirectUrl(props.href);
22
- else props.onClick(e);
23
- }
24
-
25
- const style = (props.text)
26
- ? { backgroundColor: props.color, "& span": { marginRight: 1 } }
27
- : { minWidth: "auto", padding: "4px 4px" }
28
-
29
- if (redirectUrl) return <Navigate to={redirectUrl} />
30
- else return (
31
- <Tooltip title={props.toolTip || ""} arrow placement="top">
32
- <Button sx={style} disabled={props.disabled} variant={props.text ? "outlined" : "text"} color={props.color} aria-label={props.ariaLabel || "editButton"} onClick={handleClick} size="small">
33
- <Icon>{props.icon}</Icon>{(props.text) ? props.text : ""}
34
- </Button>
35
- </Tooltip>
36
- );
37
- });
38
-
39
- SmallButton.displayName = "SmallButton";
1
+ import React from "react";
2
+ import { Button, Icon, Tooltip } from "@mui/material";
3
+ import { Navigate } from "react-router-dom";
4
+
5
+ interface Props {
6
+ ariaLabel?: string;
7
+ text?: string;
8
+ icon: string;
9
+ color?: "inherit" | "primary" | "secondary" | "success" | "error" | "info" | "warning";
10
+ toolTip?: string;
11
+ onClick?: (e: React.MouseEvent) => void;
12
+ href?: string;
13
+ disabled?: boolean
14
+ }
15
+
16
+ export const SmallButton = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
17
+ const [redirectUrl, setRedirectUrl] = React.useState("");
18
+
19
+ const handleClick = (e: React.MouseEvent) => {
20
+ e.preventDefault();
21
+ if (props.href) setRedirectUrl(props.href);
22
+ else props.onClick(e);
23
+ }
24
+
25
+ const style = (props.text)
26
+ ? { backgroundColor: props.color, "& span": { marginRight: 1 } }
27
+ : { minWidth: "auto", padding: "4px 4px" }
28
+
29
+ if (redirectUrl) return <Navigate to={redirectUrl} />
30
+ else return (
31
+ <Tooltip title={props.toolTip || ""} arrow placement="top">
32
+ <Button sx={style} disabled={props.disabled} variant={props.text ? "outlined" : "text"} color={props.color} aria-label={props.ariaLabel || "editButton"} onClick={handleClick} size="small">
33
+ <Icon>{props.icon}</Icon>{(props.text) ? props.text : ""}
34
+ </Button>
35
+ </Tooltip>
36
+ );
37
+ });
38
+
39
+ SmallButton.displayName = "SmallButton";
@@ -1,26 +1,26 @@
1
- import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Icon, Stack } from "@mui/material";
2
- import React from "react";
3
-
4
- interface Props {
5
- appName?: string
6
- onClose: () => void
7
- }
8
-
9
- export const SupportModal: React.FC<Props> = ({ appName = "", onClose }) => {
10
- const subject = appName ? `?subject=${appName} Support` : ""
11
-
12
- return (<>
13
- <Dialog open={true} onClose={onClose}>
14
- <DialogTitle>Get Support</DialogTitle>
15
- <DialogContent>
16
- <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}} mb={2}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>mail</Icon> Email:</Stack></b> <a href={"mailto:support@livecs.org" + subject}>support@livecs.org</a></Stack>
17
- <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}} mb={2}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>phone_iphone</Icon> Phone:</Stack></b> <a href="tel:+19189942638">+1 (918) 994-2638</a></Stack>
18
- <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}} mb={2}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>forum</Icon> Messenger:</Stack></b> <a href="https://m.me/livecsolutions" target="_new">https://m.me/livecsolutions</a></Stack>
19
- <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>info</Icon> Knowledge Base:</Stack></b> <a href="https://support.churchapps.org" target="_new">https://support.churchapps.org</a></Stack>
20
- </DialogContent>
21
- <DialogActions sx={{ paddingX: "16px", paddingBottom: "12px" }}>
22
- <Button variant="outlined" onClick={onClose}>Close</Button>
23
- </DialogActions>
24
- </Dialog>
25
- </>);
26
- };
1
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Icon, Stack } from "@mui/material";
2
+ import React from "react";
3
+
4
+ interface Props {
5
+ appName?: string
6
+ onClose: () => void
7
+ }
8
+
9
+ export const SupportModal: React.FC<Props> = ({ appName = "", onClose }) => {
10
+ const subject = appName ? `?subject=${appName} Support` : ""
11
+
12
+ return (<>
13
+ <Dialog open={true} onClose={onClose}>
14
+ <DialogTitle>Get Support</DialogTitle>
15
+ <DialogContent>
16
+ <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}} mb={2}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>mail</Icon> Email:</Stack></b> <a href={"mailto:support@livecs.org" + subject}>support@livecs.org</a></Stack>
17
+ <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}} mb={2}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>phone_iphone</Icon> Phone:</Stack></b> <a href="tel:+19189942638">+1 (918) 994-2638</a></Stack>
18
+ <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}} mb={2}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>forum</Icon> Messenger:</Stack></b> <a href="https://m.me/livecsolutions" target="_new">https://m.me/livecsolutions</a></Stack>
19
+ <Stack direction="row" alignItems="center" sx={{flexWrap: "wrap"}}><b><Stack direction="row" alignItems="center" mr="5px"><Icon sx={{marginRight: "5px"}}>info</Icon> Knowledge Base:</Stack></b> <a href="https://support.churchapps.org" target="_new">https://support.churchapps.org</a></Stack>
20
+ </DialogContent>
21
+ <DialogActions sx={{ paddingX: "16px", paddingBottom: "12px" }}>
22
+ <Button variant="outlined" onClick={onClose}>Close</Button>
23
+ </DialogActions>
24
+ </Dialog>
25
+ </>);
26
+ };