Replace Register/Login Page
Description
This document provides instructions on how to substitute the default register/login page with a custom component. This is particularly valuable when you want to incorporate personalized elements into the register/login page, such as a custom header, footer, or custom form fields.
Example
Create form input components
As a first step, you need to create form inputs for the pages going to be replaced. This is important to manage the form state and to validate the form inputs.
Create a Text Input component
Create a file named
InputFormItem.tsx
in thesrc/components/user/form-block
folder.Add the following code to the
InputFormItem.tsx
file.
import React from "react";
import { Control, Controller } from "react-hook-form";
import {
TextInputProps,
TextInput,
View,
Text,
StyleSheet,
} from "react-native";
type Props = {
control: Control;
name: string;
label: string;
style?: any;
} & TextInputProps;
export function InputFormItem({
control,
name,
label,
style = {},
...props
}: Props) {
return (
<Controller
control={control}
name={name}
render={({ field: { onChange, value, onBlur }, fieldState }) => (
<View style={styles.container}>
<TextInput
value={value}
onChangeText={onChange}
style={styles.input}
{...props}
/>
{fieldState.error && (
<Text style={styles.errorText}>
{fieldState.error && fieldState.error.message}
</Text>
)}
</View>
)}
/>
);
}
const styles = StyleSheet.create({
container: {
marginBottom: 12,
},
input: {
backgroundColor: "#E8ECF4",
padding: 10,
height: 40,
},
errorText: {
color: "#EF4444",
fontSize: 12,
marginTop: 2,
},
});
The InputFormItem
component is used to create form inputs for the register/login page. This component is used to manage the form state and to validate the form inputs. You can customize components rendered in the Controller
to match your requirements.
Refer to the react-hook-form documentation for your additional requirements.
Create a Checkbox component
Create a file named
CheckboxFormItem.tsx
in thesrc/components/user/form-block
folder.Add the following code to the
CheckboxFormItem.tsx
file.
import React from "react";
import { CheckBox } from "@appmaker-xyz/ui";
import { Control, Controller } from "react-hook-form";
type Props = {
control: Control;
name: string;
label: string;
style?: any;
};
export function CheckBoxFormItem({ control, name, label, style = {} }: Props) {
return (
<Controller
control={control}
name={name}
render={({ field: { onChange, value, onBlur }, fieldState }) => (
<CheckBox
small={true}
label={label}
onValueChange={onChange}
value={value}
error={fieldState.error && fieldState.error.message}
/>
)}
/>
);
}
You can customize components rendered in the Controller
to match your requirements.
Steps to replace the register page
Create a component named
RegisterForm.js
in thesrc/components/user
folder.Add the following code to the
RegisterForm.js
file.
import React from "react";
import {
StyleSheet,
KeyboardAvoidingView,
Pressable,
Text,
ActivityIndicator,
View,
} from "react-native";
import { InputFormItem } from "./form-block/InputFormItem";
import { CheckBoxFormItem } from "./form-block/CheckBoxFormItem";
import { useRegister, useNavigationActions } from "@appmaker-xyz/shopify";
const RegisterForm = () => {
const { control, isLoading, submitRegister } = useRegister({
defaultValues: {},
});
const { openLoginPage } = useNavigationActions();
return (
<View style={styles.container}>
<Text style={styles.title}>Hello! Register now to get started</Text>
<KeyboardAvoidingView behavior="padding">
<InputFormItem
control={control}
name="first_name"
placeholder={"First Name"}
/>
<InputFormItem
control={control}
name="last_name"
placeholder={"Last Name"}
/>
<InputFormItem control={control} name="email" placeholder={"Email"} />
<InputFormItem
control={control}
name="password"
placeholder={"Password"}
autoCapitalize="none"
autoCorrect={false}
textContentType="password"
secureTextEntry={true}
/>
<InputFormItem
control={control}
secureTextEntry={true}
name="repeat_password"
placeholder={"Confirm Password"}
textContentType="password"
/>
<CheckBoxFormItem
control={control}
name="accepts_marketing"
label="Agree to receive promotions and news by email"
/>
<CheckBoxFormItem
control={control}
name="agree_terms"
label="I agree to the Terms of Service"
/>
<Pressable style={styles.button} onPress={submitRegister}>
{isLoading ? (
<ActivityIndicator size="small" color="#fff" />
) : (
<Text style={styles.buttonText}>Register</Text>
)}
</Pressable>
</KeyboardAvoidingView>
<View style={styles.signUpButton}>
<Pressable onPress={openLoginPage}>
<Text>
Already have an account?{" "}
<Text style={styles.loginText}>Login Now</Text>
</Text>
</Pressable>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {},
title: {
marginBottom: 32,
fontSize: 32,
},
button: {
alignItems: "center",
backgroundColor: "#000",
padding: 10,
},
buttonText: {
color: "#fff",
},
signUpButton: {
marginTop: 32,
alignItems: "center",
},
loginText: {
color: "#427FD1",
},
});
export default RegisterForm;
useRegister
hook is used to manage the register form state and to submit the register form. useNavigationActions
hook is used to navigate to other pages.
Refer to the useRegister and useNavigationActions hooks for more information.
- Register the
RegisterForm
component in thesrc/blocks/index.js
file.
import RegisterForm from "../components/user/RegisterForm";
const blocks = [
{
name: "appmaker/register-form",
View: RegisterForm,
},
];
export { blocks };
Create a page file named
Register.js
in thesrc/pages
folder.Add the following code to the
Register.js
file.
const Register = {
type: "normal",
title: "Register",
attributes: {
renderType: "normal",
renderInScroll: true,
rootContainerStyle: {
flex: 1,
backgroundColor: "#FFFFFF",
},
contentContainerStyle: {
flex: 1,
},
scrollViewContentContainerStyle: {
justifyContent: "center",
padding: 12,
flexGrow: 1,
},
},
blocks: [
{
name: "appmaker/register-form",
attributes: {},
},
],
};
export default Register;
setting renderType: 'normal'
and renderInScroll
to true
will render the page in a scroll view. Which helps to render the page in a scroll view when the keyboard is open. scrollViewContentContainerStyle
is used to style the scroll view content container.
- import the
Register
page in thesrc/pages/index.js
file.
import Register from "./Register";
const pages = {
Register, //name of the page should remain as Register
};
export { pages };
Ensure that you include the pages
module within the registerTheme
function located in the src/index.js
file.
- Check whether the register page is replaced with the custom register page.
Steps to replace the login page
Create a component named
LoginForm.js
in thesrc/components/user
folder.Add the following code to the
LoginForm.js
file.
import React from "react";
import {
StyleSheet,
View,
Text,
KeyboardAvoidingView,
Pressable,
ActivityIndicator,
} from "react-native";
import { useLogin, useNavigationActions } from "@appmaker-xyz/shopify";
import { InputFormItem } from "./form-block/InputFormItem";
const LoginForm = () => {
const { control, isLoading, submitLogin } = useLogin({
defaultValues: {
email: "",
password: "",
},
});
const { openRegister, openResetPassword } = useNavigationActions();
return (
<View style={styles.container}>
<KeyboardAvoidingView behavior="padding">
<InputFormItem control={control} name="email" placeholder="Email" />
<InputFormItem
control={control}
name="password"
placeholder="Password"
secureTextEntry={true}
/>
<Pressable style={styles.forgotButton} onPress={openResetPassword}>
<Text size="sm" color="#868E96">
Forgot Password?
</Text>
</Pressable>
<Pressable style={styles.button} onPress={submitLogin}>
{isLoading ? (
<ActivityIndicator size="small" color="#fff" />
) : (
<Text style={styles.buttonText}>Login</Text>
)}
</Pressable>
</KeyboardAvoidingView>
<View style={styles.signUpButton}>
<Pressable onPress={openRegister}>
<Text>
Don't have an account?{" "}
<Text style={styles.signUpText}>Sign up</Text>
</Text>
</Pressable>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {},
forgotButton: {
alignSelf: "flex-end",
marginBottom: 16,
marginTop: -6,
},
button: {
alignItems: "center",
backgroundColor: "#000",
padding: 10,
},
buttonText: {
color: "#fff",
},
signUpButton: {
marginTop: 32,
alignItems: "center",
},
signUpText: {
color: "#427FD1",
},
});
export default LoginForm;
useLogin
hook is used to manage the login form state and to submit the login form. useNavigationActions
hook is used to navigate to other pages.
Refer to the useLogin and useNavigationActions hooks for more information.
- Register the
LoginForm
component in thesrc/blocks/index.js
file.
import LoginForm from "../components/user/LoginForm";
const blocks = [
{
name: "appmaker/login-form",
View: LoginForm,
},
];
export { blocks };
Create a page file named
LoginPage.js
in thesrc/pages
folder.Add the following code to the
LoginPage.js
file.
import { appSettings } from "@appmaker-xyz/core";
const appmakerImages = appSettings.getOption("appmakerImages");
const LoginPage = {
type: "normal",
title: "Login",
attributes: {
renderType: "normal",
renderInScroll: true,
rootContainerStyle: {
flex: 1,
backgroundColor: "#FFFFFF",
},
contentContainerStyle: {
flex: 1,
},
scrollViewContentContainerStyle: {
justifyContent: "center",
padding: 12,
flexGrow: 1,
},
},
blocks: [
{
name: "appmaker/appImage",
attributes: {
style: {
width: 200,
height: 60,
alignSelf: "center",
resizeMode: "contain",
marginBottom: 18,
},
src: appmakerImages.loginLogo,
},
},
{
name: "appmaker/login-form",
attributes: {},
},
],
};
export default LoginPage;
appmaker/appImage
block is used to render the an image. appmakerImages
is used to get the app logo image url. You can use the appmakerImages
object as mentioned in the above example to get the app logo image url, which is uploaded in the appmaker dashboard.
- import the
LoginPage
page in thesrc/pages/index.js
file.
import LoginPage from "./LoginPage";
const pages = {
LoginPage, //name of the page should remain as LoginPage
};
export { pages };
- Check whether the login page is replaced with the custom login page.
Steps to replace the forgot password page
Create a component named
ResetPasswordForm.js
in thesrc/components/user
folder.Add the following code to the
ResetPasswordForm.js
file.
import React from "react";
import {
StyleSheet,
KeyboardAvoidingView,
Pressable,
ActivityIndicator,
Text,
View,
} from "react-native";
import Icon from "react-native-vector-icons/Feather";
import { useNavigationActions, useForgotPassword } from "@appmaker-xyz/shopify";
import { InputFormItem } from "./form-block/InputFormItem";
const ResetPasswordForm = ({ onAction }) => {
const { control, isLoading, submit, isSuccess } = useForgotPassword({
defaultValues: {
email: "",
},
});
const { openLoginPage } = useNavigationActions();
if (isSuccess) {
return (
<View style={styles.container}>
<Icon name="check-circle" size={40} color="#064E3B" />
<Text style={styles.largeText}>Reset Link Sent</Text>
<Text style={styles.title}>
We've sent you an email with a link to update your password. Please
check your inbox.
</Text>
<Pressable style={styles.button} onPress={openLoginPage}>
<Text style={styles.buttonText}>Back to Login</Text>
</Pressable>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.largeText}>Reset Password</Text>
<Text style={styles.title}>
Enter your email address below and we'll send you a link to reset your
password.
</Text>
<KeyboardAvoidingView behavior="padding">
<InputFormItem
keyboardType="email-address"
textContentType="emailAddress"
style={styles.input}
control={control}
name="email"
placeholder="Email"
/>
<Pressable style={styles.button} onPress={submit}>
{isLoading ? (
<ActivityIndicator size="small" color="#fff" />
) : (
<Text style={styles.buttonText}>Reset Password</Text>
)}
</Pressable>
</KeyboardAvoidingView>
</View>
);
};
const styles = StyleSheet.create({
container: {},
title: {
marginBottom: 32,
color: "#4f4f4f",
},
largeText: {
fontSize: 32,
color: "#212121",
},
button: {
alignItems: "center",
backgroundColor: "#000",
padding: 10,
},
buttonText: {
color: "#fff",
},
});
export default ResetPasswordForm;
useForgotPassword
hook is used to manage the forgot password form state and to submit the forgot password form. useNavigationActions
hook is used to navigate to other pages.
Refer to the useForgotPassword and useNavigationActions hooks for more information.
- Register the
ResetPasswordForm
component in thesrc/blocks/index.js
file.
import ResetPasswordForm from "../components/user/ResetPasswordForm";
const blocks = [
{
name: "appmaker/reset-password-form",
View: ResetPasswordForm,
},
];
export { blocks };
Create a page file named
ForgetPassword.js
in thesrc/pages
folder.Add the following code to the
ForgetPassword.js
file.
const ForgetPassword = {
type: "normal",
title: "Reset Password",
attributes: {
rootContainerStyle: {
flex: 1,
backgroundColor: "#FFFFFF",
},
contentContainerStyle: {
flex: 1,
paddingHorizontal: 12,
justifyContent: "center",
},
},
blocks: [
{
name: "appmaker/reset-password-form",
attributes: {},
},
],
};
export default ForgetPassword;
- import the
ForgetPassword
page in thesrc/pages/index.js
file.
import ForgetPassword from "./ForgetPassword";
const pages = {
ForgetPassword, //name of the page should remain as ForgetPassword
};
export { pages };
- Check whether the forgot password page is replaced with the custom forgot password page.