Skip to main content

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

App ScreenshotApp ScreenshotApp Screenshot

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

  1. Create a file named InputFormItem.tsx in the src/components/user/form-block folder.

  2. Add the following code to the InputFormItem.tsx file.

src/components/user/form-block/InputFormItem.tsx
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,
},
});
tip

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

  1. Create a file named CheckboxFormItem.tsx in the src/components/user/form-block folder.

  2. Add the following code to the CheckboxFormItem.tsx file.

src/components/user/form-block/CheckboxFormItem.tsx
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}
/>
)}
/>
);
}
tip

You can customize components rendered in the Controller to match your requirements.

Steps to replace the register page

  1. Create a component named RegisterForm.js in the src/components/user folder.

  2. Add the following code to the RegisterForm.js file.

src/components/user/RegisterForm.js
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;
info

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.

  1. Register the RegisterForm component in the src/blocks/index.js file.
src/blocks/index.js
import RegisterForm from "../components/user/RegisterForm";

const blocks = [
{
name: "appmaker/register-form",
View: RegisterForm,
},
];

export { blocks };
  1. Create a page file named Register.js in the src/pages folder.

  2. Add the following code to the Register.js file.

src/pages/Register.js
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;
note

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.

  1. import the Register page in the src/pages/index.js file.
src/pages/index.js
import Register from "./Register";

const pages = {
Register, //name of the page should remain as Register
};

export { pages };
info

Ensure that you include the pages module within the registerTheme function located in the src/index.js file.

  1. Check whether the register page is replaced with the custom register page.

Steps to replace the login page

  1. Create a component named LoginForm.js in the src/components/user folder.

  2. Add the following code to the LoginForm.js file.

src/components/user/LoginForm.js
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;
info

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.

  1. Register the LoginForm component in the src/blocks/index.js file.
src/blocks/index.js
import LoginForm from "../components/user/LoginForm";

const blocks = [
{
name: "appmaker/login-form",
View: LoginForm,
},
];

export { blocks };
  1. Create a page file named LoginPage.js in the src/pages folder.

  2. Add the following code to the LoginPage.js file.

src/pages/LoginPage.js
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;
note

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.

  1. import the LoginPage page in the src/pages/index.js file.
src/pages/index.js
import LoginPage from "./LoginPage";

const pages = {
LoginPage, //name of the page should remain as LoginPage
};

export { pages };
  1. Check whether the login page is replaced with the custom login page.

Steps to replace the forgot password page

  1. Create a component named ResetPasswordForm.js in the src/components/user folder.

  2. Add the following code to the ResetPasswordForm.js file.

src/components/user/ResetPasswordForm.js
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;
info

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.

  1. Register the ResetPasswordForm component in the src/blocks/index.js file.
src/blocks/index.js
import ResetPasswordForm from "../components/user/ResetPasswordForm";

const blocks = [
{
name: "appmaker/reset-password-form",
View: ResetPasswordForm,
},
];

export { blocks };
  1. Create a page file named ForgetPassword.js in the src/pages folder.

  2. Add the following code to the ForgetPassword.js file.

src/pages/ForgetPassword.js
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;
  1. import the ForgetPassword page in the src/pages/index.js file.
src/pages/index.js
import ForgetPassword from "./ForgetPassword";

const pages = {
ForgetPassword, //name of the page should remain as ForgetPassword
};

export { pages };
  1. Check whether the forgot password page is replaced with the custom forgot password page.