@churchapps/apphelper-login 0.5.0 → 0.5.1
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.
- package/README.md +103 -103
- package/dist/helpers/AnalyticsHelper.d.ts.map +1 -1
- package/dist/helpers/AnalyticsHelper.js +21 -6
- package/dist/helpers/AnalyticsHelper.js.map +1 -1
- package/package.json +57 -57
- package/src/LoginPage.tsx +305 -305
- package/src/LogoutPage.tsx +43 -43
- package/src/components/Forgot.tsx +246 -246
- package/src/components/Login.tsx +305 -305
- package/src/components/LoginSetPassword.tsx +297 -297
- package/src/components/Register.tsx +370 -370
- package/src/components/SelectChurchModal.tsx +88 -88
- package/src/components/SelectChurchRegister.tsx +88 -88
- package/src/components/SelectChurchSearch.tsx +85 -85
- package/src/components/SelectableChurch.tsx +114 -114
- package/src/helpers/AnalyticsHelper.ts +44 -32
- package/src/helpers/Locale.ts +248 -248
- package/src/helpers/index.ts +1 -1
- package/src/index.ts +10 -10
- package/tsconfig.json +29 -29
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { ChurchInterface, LoginUserChurchInterface } from "@churchapps/helpers";
|
|
5
|
-
import { SelectChurchSearch } from "./SelectChurchSearch";
|
|
6
|
-
import { SelectableChurch } from "./SelectableChurch";
|
|
7
|
-
import { ErrorMessages } from "@churchapps/apphelper"
|
|
8
|
-
import { Dialog, DialogContent, DialogTitle, IconButton, Tooltip, Box } from "@mui/material";
|
|
9
|
-
import { Logout } from "@mui/icons-material";
|
|
10
|
-
import { Locale } from "../helpers";
|
|
11
|
-
|
|
12
|
-
interface Props {
|
|
13
|
-
appName: string,
|
|
14
|
-
show: boolean,
|
|
15
|
-
userChurches?: LoginUserChurchInterface[],
|
|
16
|
-
selectChurch: (churchId: string) => void,
|
|
17
|
-
registeredChurchCallback?: (church: ChurchInterface) => void,
|
|
18
|
-
errors?: string[],
|
|
19
|
-
handleRedirect?: (url: string) => void
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const SelectChurchModal: React.FC<Props> = (props) => {
|
|
23
|
-
const [showSearch, setShowSearch] = React.useState(false);
|
|
24
|
-
|
|
25
|
-
const handleClose = () => {
|
|
26
|
-
window.location.reload();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const getContents = () => {
|
|
30
|
-
if (showSearch || props.userChurches?.length === 0) return <SelectChurchSearch selectChurch={props.selectChurch} registeredChurchCallback={props.registeredChurchCallback} appName={props.appName} />
|
|
31
|
-
else return (<>
|
|
32
|
-
{props.userChurches?.map(uc => (<SelectableChurch church={uc.church} selectChurch={props.selectChurch} key={uc.church.id} />))}
|
|
33
|
-
<Box sx={{ textAlign: "center", mt: 3 }}>
|
|
34
|
-
<button
|
|
35
|
-
type="button"
|
|
36
|
-
style={{
|
|
37
|
-
display: "inline-block",
|
|
38
|
-
background: "none",
|
|
39
|
-
border: "none",
|
|
40
|
-
color: "#3b82f6",
|
|
41
|
-
cursor: "pointer",
|
|
42
|
-
textDecoration: "none",
|
|
43
|
-
fontSize: "1rem",
|
|
44
|
-
transition: "all 0.2s ease"
|
|
45
|
-
}}
|
|
46
|
-
onClick={(e) => { e.preventDefault(); setShowSearch(true); }}
|
|
47
|
-
onMouseEnter={(e) => e.currentTarget.style.textDecoration = "underline"}
|
|
48
|
-
onMouseLeave={(e) => e.currentTarget.style.textDecoration = "none"}
|
|
49
|
-
>
|
|
50
|
-
{Locale.label("selectChurch.another")}
|
|
51
|
-
</button>
|
|
52
|
-
</Box>
|
|
53
|
-
</>);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<Dialog
|
|
58
|
-
open={props.show}
|
|
59
|
-
onClose={handleClose}
|
|
60
|
-
aria-labelledby="select-church-title"
|
|
61
|
-
aria-describedby="select-church-content"
|
|
62
|
-
>
|
|
63
|
-
<DialogTitle id="select-church-title" sx={{ fontSize: "1.5rem", fontWeight: 600 }}>
|
|
64
|
-
{Locale.label("selectChurch.selectChurch")}
|
|
65
|
-
</DialogTitle>
|
|
66
|
-
<Tooltip title="Logout" arrow>
|
|
67
|
-
<IconButton
|
|
68
|
-
sx={{ position: "absolute", right: 8, top: 8 }}
|
|
69
|
-
color="error"
|
|
70
|
-
aria-label="Logout"
|
|
71
|
-
onClick={() => {
|
|
72
|
-
// Use handleRedirect function if available, otherwise fallback to window.location
|
|
73
|
-
if (props.handleRedirect) {
|
|
74
|
-
props.handleRedirect("/logout");
|
|
75
|
-
} else {
|
|
76
|
-
window.location.href = "/logout";
|
|
77
|
-
}
|
|
78
|
-
}}>
|
|
79
|
-
<Logout />
|
|
80
|
-
</IconButton>
|
|
81
|
-
</Tooltip>
|
|
82
|
-
<DialogContent id="select-church-content" sx={{ width: 700, maxWidth: "100%", px: 2, py: 2 }}>
|
|
83
|
-
<ErrorMessages errors={props.errors} />
|
|
84
|
-
{getContents()}
|
|
85
|
-
</DialogContent>
|
|
86
|
-
</Dialog>
|
|
87
|
-
);
|
|
88
|
-
};
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { ChurchInterface, LoginUserChurchInterface } from "@churchapps/helpers";
|
|
5
|
+
import { SelectChurchSearch } from "./SelectChurchSearch";
|
|
6
|
+
import { SelectableChurch } from "./SelectableChurch";
|
|
7
|
+
import { ErrorMessages } from "@churchapps/apphelper"
|
|
8
|
+
import { Dialog, DialogContent, DialogTitle, IconButton, Tooltip, Box } from "@mui/material";
|
|
9
|
+
import { Logout } from "@mui/icons-material";
|
|
10
|
+
import { Locale } from "../helpers";
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
appName: string,
|
|
14
|
+
show: boolean,
|
|
15
|
+
userChurches?: LoginUserChurchInterface[],
|
|
16
|
+
selectChurch: (churchId: string) => void,
|
|
17
|
+
registeredChurchCallback?: (church: ChurchInterface) => void,
|
|
18
|
+
errors?: string[],
|
|
19
|
+
handleRedirect?: (url: string) => void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const SelectChurchModal: React.FC<Props> = (props) => {
|
|
23
|
+
const [showSearch, setShowSearch] = React.useState(false);
|
|
24
|
+
|
|
25
|
+
const handleClose = () => {
|
|
26
|
+
window.location.reload();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getContents = () => {
|
|
30
|
+
if (showSearch || props.userChurches?.length === 0) return <SelectChurchSearch selectChurch={props.selectChurch} registeredChurchCallback={props.registeredChurchCallback} appName={props.appName} />
|
|
31
|
+
else return (<>
|
|
32
|
+
{props.userChurches?.map(uc => (<SelectableChurch church={uc.church} selectChurch={props.selectChurch} key={uc.church.id} />))}
|
|
33
|
+
<Box sx={{ textAlign: "center", mt: 3 }}>
|
|
34
|
+
<button
|
|
35
|
+
type="button"
|
|
36
|
+
style={{
|
|
37
|
+
display: "inline-block",
|
|
38
|
+
background: "none",
|
|
39
|
+
border: "none",
|
|
40
|
+
color: "#3b82f6",
|
|
41
|
+
cursor: "pointer",
|
|
42
|
+
textDecoration: "none",
|
|
43
|
+
fontSize: "1rem",
|
|
44
|
+
transition: "all 0.2s ease"
|
|
45
|
+
}}
|
|
46
|
+
onClick={(e) => { e.preventDefault(); setShowSearch(true); }}
|
|
47
|
+
onMouseEnter={(e) => e.currentTarget.style.textDecoration = "underline"}
|
|
48
|
+
onMouseLeave={(e) => e.currentTarget.style.textDecoration = "none"}
|
|
49
|
+
>
|
|
50
|
+
{Locale.label("selectChurch.another")}
|
|
51
|
+
</button>
|
|
52
|
+
</Box>
|
|
53
|
+
</>);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Dialog
|
|
58
|
+
open={props.show}
|
|
59
|
+
onClose={handleClose}
|
|
60
|
+
aria-labelledby="select-church-title"
|
|
61
|
+
aria-describedby="select-church-content"
|
|
62
|
+
>
|
|
63
|
+
<DialogTitle id="select-church-title" sx={{ fontSize: "1.5rem", fontWeight: 600 }}>
|
|
64
|
+
{Locale.label("selectChurch.selectChurch")}
|
|
65
|
+
</DialogTitle>
|
|
66
|
+
<Tooltip title="Logout" arrow>
|
|
67
|
+
<IconButton
|
|
68
|
+
sx={{ position: "absolute", right: 8, top: 8 }}
|
|
69
|
+
color="error"
|
|
70
|
+
aria-label="Logout"
|
|
71
|
+
onClick={() => {
|
|
72
|
+
// Use handleRedirect function if available, otherwise fallback to window.location
|
|
73
|
+
if (props.handleRedirect) {
|
|
74
|
+
props.handleRedirect("/logout");
|
|
75
|
+
} else {
|
|
76
|
+
window.location.href = "/logout";
|
|
77
|
+
}
|
|
78
|
+
}}>
|
|
79
|
+
<Logout />
|
|
80
|
+
</IconButton>
|
|
81
|
+
</Tooltip>
|
|
82
|
+
<DialogContent id="select-church-content" sx={{ width: 700, maxWidth: "100%", px: 2, py: 2 }}>
|
|
83
|
+
<ErrorMessages errors={props.errors} />
|
|
84
|
+
{getContents()}
|
|
85
|
+
</DialogContent>
|
|
86
|
+
</Dialog>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { ApiHelper } from "@churchapps/helpers";
|
|
5
|
-
import { Locale } from "../helpers";
|
|
6
|
-
import { ChurchInterface, RegisterChurchRequestInterface } from "@churchapps/helpers";
|
|
7
|
-
import { ErrorMessages, InputBox } from "@churchapps/apphelper"
|
|
8
|
-
import { Grid, TextField } from "@mui/material";
|
|
9
|
-
|
|
10
|
-
interface Props {
|
|
11
|
-
initialChurchName: string,
|
|
12
|
-
registeredChurchCallback?: (church: ChurchInterface) => void,
|
|
13
|
-
selectChurch: (churchId: string) => void,
|
|
14
|
-
appName: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const SelectChurchRegister: React.FC<Props> = (props) => {
|
|
18
|
-
const suggestSubDomain = (name: string) => {
|
|
19
|
-
let result = name.toLowerCase().replaceAll("christian", "").replaceAll("church", "").replaceAll(" ", "");
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const [church, setChurch] = React.useState<RegisterChurchRequestInterface>({ name: props.initialChurchName, appName: props.appName, subDomain: suggestSubDomain(props.initialChurchName) });
|
|
24
|
-
const [errors, setErrors] = React.useState([]);
|
|
25
|
-
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
26
|
-
|
|
27
|
-
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
28
|
-
const c = { ...church }
|
|
29
|
-
switch (e.target.name) {
|
|
30
|
-
case "churchName": c.name = e.target.value; break;
|
|
31
|
-
case "subDomain": c.subDomain = e.target.value; break;
|
|
32
|
-
case "address1": c.address1 = e.target.value; break;
|
|
33
|
-
case "address2": c.address2 = e.target.value; break;
|
|
34
|
-
case "city": c.city = e.target.value; break;
|
|
35
|
-
case "state": c.state = e.target.value; break;
|
|
36
|
-
case "zip": c.zip = e.target.value; break;
|
|
37
|
-
case "country": c.country = e.target.value; break;
|
|
38
|
-
}
|
|
39
|
-
setChurch(c);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const validate = () => {
|
|
43
|
-
let errors = [];
|
|
44
|
-
if (!church.name?.trim()) errors.push(Locale.label("selectChurch.validate.name"));
|
|
45
|
-
if (!church.address1?.trim()) errors.push(Locale.label("selectChurch.validate.address"));
|
|
46
|
-
if (!church.city?.trim()) errors.push(Locale.label("selectChurch.validate.city"));
|
|
47
|
-
if (!church.state?.trim()) errors.push(Locale.label("selectChurch.validate.state"));
|
|
48
|
-
if (!church.zip?.trim()) errors.push(Locale.label("selectChurch.validate.zip"));
|
|
49
|
-
if (!church.country?.trim()) errors.push(Locale.label("selectChurch.validate.country"));
|
|
50
|
-
setErrors(errors);
|
|
51
|
-
return errors.length === 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const handleSave = () => {
|
|
55
|
-
if (validate()) {
|
|
56
|
-
setIsSubmitting(true);
|
|
57
|
-
const c = { ...church };
|
|
58
|
-
if (!c.subDomain) c.subDomain = suggestSubDomain(c.name);
|
|
59
|
-
ApiHelper.post("/churches/add", church, "MembershipApi").then(async (resp: any) => {
|
|
60
|
-
setIsSubmitting(false);
|
|
61
|
-
if (resp.errors !== undefined) setErrors(errors);
|
|
62
|
-
else {
|
|
63
|
-
if (props.registeredChurchCallback) props.registeredChurchCallback(resp);
|
|
64
|
-
props.selectChurch(resp.id);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<InputBox id="churchBox" saveFunction={handleSave} headerText={Locale.label("selectChurch.register")} headerIcon="church" isSubmitting={isSubmitting}>
|
|
72
|
-
<ErrorMessages errors={errors} />
|
|
73
|
-
<TextField required fullWidth name="churchName" label={Locale.label("selectChurch.name")} value={church.name} onChange={handleChange} />
|
|
74
|
-
|
|
75
|
-
<TextField required fullWidth name="address1" label={Locale.label("selectChurch.address1")} value={church.address1} onChange={handleChange} />
|
|
76
|
-
<Grid container spacing={3}>
|
|
77
|
-
<Grid size={6}><TextField fullWidth name="address2" label={Locale.label("selectChurch.address2")} value={church.address2} onChange={handleChange} /></Grid>
|
|
78
|
-
<Grid size={6}><TextField required fullWidth name="city" label={Locale.label("selectChurch.city")} value={church.city} onChange={handleChange} /></Grid>
|
|
79
|
-
</Grid>
|
|
80
|
-
<Grid container spacing={3}>
|
|
81
|
-
<Grid size={6}><TextField required fullWidth name="state" label={Locale.label("selectChurch.state")} value={church.state} onChange={handleChange} /></Grid>
|
|
82
|
-
<Grid size={6}><TextField required fullWidth name="zip" label={Locale.label("selectChurch.zip")} value={church.zip} onChange={handleChange} /></Grid>
|
|
83
|
-
</Grid>
|
|
84
|
-
<TextField required fullWidth name="country" label={Locale.label("selectChurch.country")} value={church.country} onChange={handleChange} />
|
|
85
|
-
</InputBox>
|
|
86
|
-
);
|
|
87
|
-
};
|
|
88
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { ApiHelper } from "@churchapps/helpers";
|
|
5
|
+
import { Locale } from "../helpers";
|
|
6
|
+
import { ChurchInterface, RegisterChurchRequestInterface } from "@churchapps/helpers";
|
|
7
|
+
import { ErrorMessages, InputBox } from "@churchapps/apphelper"
|
|
8
|
+
import { Grid, TextField } from "@mui/material";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
initialChurchName: string,
|
|
12
|
+
registeredChurchCallback?: (church: ChurchInterface) => void,
|
|
13
|
+
selectChurch: (churchId: string) => void,
|
|
14
|
+
appName: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const SelectChurchRegister: React.FC<Props> = (props) => {
|
|
18
|
+
const suggestSubDomain = (name: string) => {
|
|
19
|
+
let result = name.toLowerCase().replaceAll("christian", "").replaceAll("church", "").replaceAll(" ", "");
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const [church, setChurch] = React.useState<RegisterChurchRequestInterface>({ name: props.initialChurchName, appName: props.appName, subDomain: suggestSubDomain(props.initialChurchName) });
|
|
24
|
+
const [errors, setErrors] = React.useState([]);
|
|
25
|
+
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
26
|
+
|
|
27
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
28
|
+
const c = { ...church }
|
|
29
|
+
switch (e.target.name) {
|
|
30
|
+
case "churchName": c.name = e.target.value; break;
|
|
31
|
+
case "subDomain": c.subDomain = e.target.value; break;
|
|
32
|
+
case "address1": c.address1 = e.target.value; break;
|
|
33
|
+
case "address2": c.address2 = e.target.value; break;
|
|
34
|
+
case "city": c.city = e.target.value; break;
|
|
35
|
+
case "state": c.state = e.target.value; break;
|
|
36
|
+
case "zip": c.zip = e.target.value; break;
|
|
37
|
+
case "country": c.country = e.target.value; break;
|
|
38
|
+
}
|
|
39
|
+
setChurch(c);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const validate = () => {
|
|
43
|
+
let errors = [];
|
|
44
|
+
if (!church.name?.trim()) errors.push(Locale.label("selectChurch.validate.name"));
|
|
45
|
+
if (!church.address1?.trim()) errors.push(Locale.label("selectChurch.validate.address"));
|
|
46
|
+
if (!church.city?.trim()) errors.push(Locale.label("selectChurch.validate.city"));
|
|
47
|
+
if (!church.state?.trim()) errors.push(Locale.label("selectChurch.validate.state"));
|
|
48
|
+
if (!church.zip?.trim()) errors.push(Locale.label("selectChurch.validate.zip"));
|
|
49
|
+
if (!church.country?.trim()) errors.push(Locale.label("selectChurch.validate.country"));
|
|
50
|
+
setErrors(errors);
|
|
51
|
+
return errors.length === 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handleSave = () => {
|
|
55
|
+
if (validate()) {
|
|
56
|
+
setIsSubmitting(true);
|
|
57
|
+
const c = { ...church };
|
|
58
|
+
if (!c.subDomain) c.subDomain = suggestSubDomain(c.name);
|
|
59
|
+
ApiHelper.post("/churches/add", church, "MembershipApi").then(async (resp: any) => {
|
|
60
|
+
setIsSubmitting(false);
|
|
61
|
+
if (resp.errors !== undefined) setErrors(errors);
|
|
62
|
+
else {
|
|
63
|
+
if (props.registeredChurchCallback) props.registeredChurchCallback(resp);
|
|
64
|
+
props.selectChurch(resp.id);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<InputBox id="churchBox" saveFunction={handleSave} headerText={Locale.label("selectChurch.register")} headerIcon="church" isSubmitting={isSubmitting}>
|
|
72
|
+
<ErrorMessages errors={errors} />
|
|
73
|
+
<TextField required fullWidth name="churchName" label={Locale.label("selectChurch.name")} value={church.name} onChange={handleChange} />
|
|
74
|
+
|
|
75
|
+
<TextField required fullWidth name="address1" label={Locale.label("selectChurch.address1")} value={church.address1} onChange={handleChange} />
|
|
76
|
+
<Grid container spacing={3}>
|
|
77
|
+
<Grid size={6}><TextField fullWidth name="address2" label={Locale.label("selectChurch.address2")} value={church.address2} onChange={handleChange} /></Grid>
|
|
78
|
+
<Grid size={6}><TextField required fullWidth name="city" label={Locale.label("selectChurch.city")} value={church.city} onChange={handleChange} /></Grid>
|
|
79
|
+
</Grid>
|
|
80
|
+
<Grid container spacing={3}>
|
|
81
|
+
<Grid size={6}><TextField required fullWidth name="state" label={Locale.label("selectChurch.state")} value={church.state} onChange={handleChange} /></Grid>
|
|
82
|
+
<Grid size={6}><TextField required fullWidth name="zip" label={Locale.label("selectChurch.zip")} value={church.zip} onChange={handleChange} /></Grid>
|
|
83
|
+
</Grid>
|
|
84
|
+
<TextField required fullWidth name="country" label={Locale.label("selectChurch.country")} value={church.country} onChange={handleChange} />
|
|
85
|
+
</InputBox>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Button, TextField } from "@mui/material";
|
|
4
|
-
import React from "react";
|
|
5
|
-
import { ApiHelper } from "@churchapps/helpers";
|
|
6
|
-
import { Locale } from "../helpers";
|
|
7
|
-
import { ChurchInterface } from "@churchapps/helpers";
|
|
8
|
-
import { SelectableChurch } from "./SelectableChurch";
|
|
9
|
-
import { SelectChurchRegister } from "./SelectChurchRegister";
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
selectChurch: (churchId: string) => void,
|
|
13
|
-
registeredChurchCallback?: (church: ChurchInterface) => void,
|
|
14
|
-
appName: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const SelectChurchSearch: React.FC<Props> = (props) => {
|
|
18
|
-
const [searchText, setSearchText] = React.useState("");
|
|
19
|
-
const [churches, setChurches] = React.useState<ChurchInterface[]>(null);
|
|
20
|
-
const [showRegister, setShowRegister] = React.useState(false);
|
|
21
|
-
|
|
22
|
-
const handleSubmit = (e: React.MouseEvent) => {
|
|
23
|
-
if (e !== null) e.preventDefault();
|
|
24
|
-
let term = searchText.trim();
|
|
25
|
-
ApiHelper.post("/churches/search", { name: term }, "MembershipApi").then((data: any) => setChurches(data));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => setSearchText(e.currentTarget.value);
|
|
29
|
-
|
|
30
|
-
const handleKeyDown = (e: React.KeyboardEvent<any>) => { if (e.key === "Enter") { e.preventDefault(); handleSubmit(null); } }
|
|
31
|
-
|
|
32
|
-
const handleRegisterClick = (e: React.MouseEvent) => {
|
|
33
|
-
e.preventDefault();
|
|
34
|
-
if (window.confirm(Locale.label("selectChurch.confirmRegister"))) {
|
|
35
|
-
setShowRegister(true);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const getRegisterLink = () => (
|
|
40
|
-
<div>
|
|
41
|
-
<button
|
|
42
|
-
type="button"
|
|
43
|
-
style={{
|
|
44
|
-
display: "block",
|
|
45
|
-
textAlign: "center",
|
|
46
|
-
background: "none",
|
|
47
|
-
border: "none",
|
|
48
|
-
color: "#3b82f6",
|
|
49
|
-
cursor: "pointer",
|
|
50
|
-
textDecoration: "underline",
|
|
51
|
-
width: "100%"
|
|
52
|
-
}}
|
|
53
|
-
onClick={handleRegisterClick}
|
|
54
|
-
>
|
|
55
|
-
{Locale.label("selectChurch.register")}
|
|
56
|
-
</button>
|
|
57
|
-
</div>
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
const getChurches = () => {
|
|
61
|
-
const result: React.ReactElement[] = [];
|
|
62
|
-
churches.forEach(church => {
|
|
63
|
-
result.push(<SelectableChurch church={church} selectChurch={props.selectChurch} />);
|
|
64
|
-
});
|
|
65
|
-
result.push(getRegisterLink());
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const getResults = () => {
|
|
70
|
-
if (churches === null) return;
|
|
71
|
-
else if (churches.length === 0) return <><p>{Locale.label("selectChurch.noMatches")}</p>{getRegisterLink()}</>
|
|
72
|
-
else return getChurches();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (showRegister) return (<SelectChurchRegister selectChurch={props.selectChurch} registeredChurchCallback={props.registeredChurchCallback} appName={props.appName} initialChurchName={searchText} />)
|
|
76
|
-
else return (
|
|
77
|
-
<>
|
|
78
|
-
<TextField fullWidth name="searchText" label="Name" value={searchText} onChange={handleChange} onKeyDown={handleKeyDown}
|
|
79
|
-
InputProps={{ endAdornment: <Button variant="contained" id="searchButton" data-testid="search-button" onClick={handleSubmit}>{Locale.label("common.search")}</Button> }}
|
|
80
|
-
/>
|
|
81
|
-
{getResults()}
|
|
82
|
-
</>
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
};
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Button, TextField } from "@mui/material";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { ApiHelper } from "@churchapps/helpers";
|
|
6
|
+
import { Locale } from "../helpers";
|
|
7
|
+
import { ChurchInterface } from "@churchapps/helpers";
|
|
8
|
+
import { SelectableChurch } from "./SelectableChurch";
|
|
9
|
+
import { SelectChurchRegister } from "./SelectChurchRegister";
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
selectChurch: (churchId: string) => void,
|
|
13
|
+
registeredChurchCallback?: (church: ChurchInterface) => void,
|
|
14
|
+
appName: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const SelectChurchSearch: React.FC<Props> = (props) => {
|
|
18
|
+
const [searchText, setSearchText] = React.useState("");
|
|
19
|
+
const [churches, setChurches] = React.useState<ChurchInterface[]>(null);
|
|
20
|
+
const [showRegister, setShowRegister] = React.useState(false);
|
|
21
|
+
|
|
22
|
+
const handleSubmit = (e: React.MouseEvent) => {
|
|
23
|
+
if (e !== null) e.preventDefault();
|
|
24
|
+
let term = searchText.trim();
|
|
25
|
+
ApiHelper.post("/churches/search", { name: term }, "MembershipApi").then((data: any) => setChurches(data));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => setSearchText(e.currentTarget.value);
|
|
29
|
+
|
|
30
|
+
const handleKeyDown = (e: React.KeyboardEvent<any>) => { if (e.key === "Enter") { e.preventDefault(); handleSubmit(null); } }
|
|
31
|
+
|
|
32
|
+
const handleRegisterClick = (e: React.MouseEvent) => {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
if (window.confirm(Locale.label("selectChurch.confirmRegister"))) {
|
|
35
|
+
setShowRegister(true);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const getRegisterLink = () => (
|
|
40
|
+
<div>
|
|
41
|
+
<button
|
|
42
|
+
type="button"
|
|
43
|
+
style={{
|
|
44
|
+
display: "block",
|
|
45
|
+
textAlign: "center",
|
|
46
|
+
background: "none",
|
|
47
|
+
border: "none",
|
|
48
|
+
color: "#3b82f6",
|
|
49
|
+
cursor: "pointer",
|
|
50
|
+
textDecoration: "underline",
|
|
51
|
+
width: "100%"
|
|
52
|
+
}}
|
|
53
|
+
onClick={handleRegisterClick}
|
|
54
|
+
>
|
|
55
|
+
{Locale.label("selectChurch.register")}
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const getChurches = () => {
|
|
61
|
+
const result: React.ReactElement[] = [];
|
|
62
|
+
churches.forEach(church => {
|
|
63
|
+
result.push(<SelectableChurch church={church} selectChurch={props.selectChurch} />);
|
|
64
|
+
});
|
|
65
|
+
result.push(getRegisterLink());
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const getResults = () => {
|
|
70
|
+
if (churches === null) return;
|
|
71
|
+
else if (churches.length === 0) return <><p>{Locale.label("selectChurch.noMatches")}</p>{getRegisterLink()}</>
|
|
72
|
+
else return getChurches();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (showRegister) return (<SelectChurchRegister selectChurch={props.selectChurch} registeredChurchCallback={props.registeredChurchCallback} appName={props.appName} initialChurchName={searchText} />)
|
|
76
|
+
else return (
|
|
77
|
+
<>
|
|
78
|
+
<TextField fullWidth name="searchText" label="Name" value={searchText} onChange={handleChange} onKeyDown={handleKeyDown}
|
|
79
|
+
InputProps={{ endAdornment: <Button variant="contained" id="searchButton" data-testid="search-button" onClick={handleSubmit}>{Locale.label("common.search")}</Button> }}
|
|
80
|
+
/>
|
|
81
|
+
{getResults()}
|
|
82
|
+
</>
|
|
83
|
+
|
|
84
|
+
);
|
|
85
|
+
};
|