npm package: @manacommon/web-auth
Description: Mana Common web-auth is a collection of react components to handle all the mana common authentication.
Author: Onetree
Latest version: 1.0.8

# Mana Common WEB-AUTH

Mana Common web-auth is a collection of react components to handle all the mana common authentication.

## Installation

To install the library, you can use npm or yarn:

```bash
yarn add @manacommon/web-auth
```

## Compatibility

| Dependency | Version | Recommendation |
| ---------- | ------- | -------------- |
| Node       | 16+     | Mandatory      |
| React      | 18+     | Recommended    |

## Craco

All our packages are part of a monorepository architecture so [Craco](https://craco.js.org/docs/getting-started/) (Create React App Configuration Overrode) helps to keep all dependencies and configurations working.

In a monorepo, multiple packages or applications are managed within a single code repository, often using a tool like Lerna for dependency management and project orchestration.

When working with a monorepo, it's common to have shared React library packages that are used across different applications within the repository. These library packages may require custom configuration specific to each application.

By installing Craco as a dependency in the shared React library packages, developers gain the ability to modify the Create React App (CRA) configuration for each application without the need to eject from the default setup. This is crucial because ejecting from CRA can lead to complexities and difficulties in managing the shared codebase and dependencies.

You can install Craco in your project simply runing:

```bash
yarn add -D @craco/craco
```

or

```bash
npm i -D @craco/craco
```

Your `craco.config.js` should looks like:

```javascript
const path = require('path');
const { getLoader, loaderByName } = require('@craco/craco');

const packages = [];

packages.push(path.join(__dirname, './node_modules/@manacommon/core'));
packages.push(path.join(__dirname, './node_modules/@manacommon/web'));
packages.push(path.join(__dirname, './node_modules/@manacommon/web-auth'));

module.exports = {
  webpack: {
    configure: (webpackConfig, arg) => {
      const { isFound, match } = getLoader(
        webpackConfig,
        loaderByName('babel-loader'),
      );
      if (isFound) {
        const include = Array.isArray(match.loader.include)
          ? match.loader.include
          : [match.loader.include];

        match.loader.include = include.concat(packages);
      }
      return webpackConfig;
    },
  },
};
```

## Auth Flows

You can check the auth flow [here](https://miro.com/app/board/uXjVM426910=/?share_link_id=100818722457)

## Set up your local configuration for social logins

In order to test the social logins there are some things that you have to do.

1. Create a local record with your local IP pointing to `https://tickets-localhost.manacommon.com`. It is neccesary because all social logins have a whitelist for the redirectURI. In the case of the Apple does not allow to add a `localhost` URL.

Your hosts file should looks like:

```
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
# Added by Docker Desktop
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section
127.0.0.1 tickets-localhost.manacommon.com
```

2. Set up your local SSL certificate. You can and adding some scripts to your package.json and automate this process. You can check the example below. It is necessary because all social logins work only with HTTPS.

```json
  "scripts": {
    "start": "craco start",
    "start:https": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "craco eject",
    "start:cert": "HTTPS=true HOST=tickets-localhost.manacommon.com SSL_CRT_FILE=/Users/your-mac-user-name/tickets-localhost.manacommon.com.cert SSL_KEY_FILE=/Users/your-mac-user-name/tickets-localhost.manacommon.com.key craco start",
    "cert": "devcert generate tickets-localhost.manacommon.com"
  },
```

NOTE: Before run `start:cert` you have to run `cert` in order to generate the cert and key, after that you have to copy the generated files to the SSL_CRT_FILE and SSL_KEY_FILE routes.

## Demo Code

```javascript
import React, { useEffect, useState } from "react";

import "./App.css";

import {
  type UserInformation,
  CreatePassword,
  LoginWithEmail,
  ForgotPassword,
  VerificationCode,
  Login,
  useConfig,
  SignUp,
  OnBoarding,
  useAuthentication,
  ValidateAccount,
  Welcome,
} from "@manacommon/web-auth";

import { PageWrapper } from "@manacommon/web";

enum RenderedPage {
  LOGIN,
  LOGIN_WITH_EMAIL,
  USER_LOGGED,
  SIGN_UP,
  ON_BOARDING,
  FORGOT_PASSWORD,
  VERIFICATION_CODE,
  CREATE_PASSWORD,
  VALIDATE_ACCOUNT,
  WELCOME,
}

function App() {
  const { getLoggedUserData } = useAuthentication();

  const { setConfiguration } = useConfig();

  const [currentPage, setCurrentPage] = useState(RenderedPage.LOGIN);
  const [userEmail, setUserEmail] = useState("");
  const [code, setCode] = useState("");

  useEffect(() => {
    const urlParams = new URLSearchParams(window.location.search);
    const userId = urlParams.get("userId");
    if (userId !== null) {
      setCurrentPage(RenderedPage.WELCOME);
    }
  }, []);

  const [userLogged, setUserLogged] = useState<UserInformation>();

  useEffect(() => {
    setConfiguration({
      ENVIRONMENT: "DEVELOP",
      TF_SSO_CLIENT: "your-tf-sso-client",
      TF_SSO_SECRET: "your-tf-sso-secret",
      SECRET_KEY: "your-mana-secret",
      CLIENT: "your-mana-client",
      ENABLE_TF_AUTHENTICATION: true
    });
  }, [setConfiguration]);

  const onLoginError = (error: any) => {
    console.log("Login error: ", error);
  };

  const handleGoToLoginWithEmail = () => {
    setCurrentPage(RenderedPage.LOGIN_WITH_EMAIL);
  };

  const handlegoToSignUp = () => {
    console.log("going to sign up");
    setCurrentPage(RenderedPage.SIGN_UP);
  };

  const handleCompleteVerification = () => {
    setCurrentPage(RenderedPage.ON_BOARDING);
  };

  const handleOnSubmitSignup = () => {
    setCurrentPage(RenderedPage.VALIDATE_ACCOUNT);
  };

  const handleLoginSuccess = async () => {
    const userData = await getLoggedUserData();
    setUserLogged(userData);

    if (userData.communityId === null) {
      setCurrentPage(RenderedPage.ON_BOARDING);
    } else {
      setCurrentPage(RenderedPage.USER_LOGGED);
    }
  };

  const handleGoToForgotPassword = () => {
    setCurrentPage(RenderedPage.FORGOT_PASSWORD);
  };

  const renderPage = () => {
    switch (currentPage) {
      case RenderedPage.LOGIN:
        return (
          <Login
            redirectUri="https://tickets-localhost.manacommon.com:3000"
            handleLoginWithEmail={handleGoToLoginWithEmail}
            handleSignUp={handlegoToSignUp}
            onLoginSuccess={handleLoginSuccess}
          />
        );
      case RenderedPage.LOGIN_WITH_EMAIL:
        return (
          <LoginWithEmail
            onLoginError={onLoginError}
            onLoginSuccess={handleLoginSuccess}
            onSignUp={handlegoToSignUp}
            onForgotPassword={handleGoToForgotPassword}
          />
        );
      case RenderedPage.USER_LOGGED:
        return <PageWrapper>User Logged! {userLogged?.email}</PageWrapper>;
      case RenderedPage.SIGN_UP:
        return (
          <SignUp
            onSubmit={handleOnSubmitSignup}
            onNavigateSignIn={() => setCurrentPage(RenderedPage.LOGIN)}
            onClickTerms={() =>
              window.open("https://app.manacommon.com/terms-of-use", "_blank")
            }
            externalRegisterEmailLink={
              "https://tickets-localhost.manacommon.com:3000/"
            }
          />
        );

      case RenderedPage.FORGOT_PASSWORD:
        return (
          <ForgotPassword
            showBackButton
            onClickBack={() => setCurrentPage(RenderedPage.LOGIN_WITH_EMAIL)}
            onSendEmail={(emailOrPhone) => {
              setUserEmail(emailOrPhone);
              setCurrentPage(RenderedPage.VERIFICATION_CODE);
            }}
          />
        );
      case RenderedPage.VERIFICATION_CODE:
        return (
          <VerificationCode
            onComplete={(code: string) => {
              setCode(code);
              setCurrentPage(RenderedPage.CREATE_PASSWORD);
            }}
            userEmail={userEmail}
          />
        );
      case RenderedPage.CREATE_PASSWORD:
        return (
          <CreatePassword
            email={userEmail}
            code={code}
            onConfirm={() => setCurrentPage(RenderedPage.LOGIN)}
          />
        );
      case RenderedPage.VALIDATE_ACCOUNT:
        return <ValidateAccount />;

      case RenderedPage.WELCOME:
        return <Welcome onCompleteVerification={handleCompleteVerification} />;

      case RenderedPage.ON_BOARDING:
        return (
          <OnBoarding
            userId={userLogged?.id ?? ""}
            onComplete={() => setCurrentPage(RenderedPage.USER_LOGGED)}
          />
        );
      default:
        return <Login />;
    }
  };

  return (
    <div className="App">
      <h3>@manacommon/web Example project</h3>
      {renderPage()}
    </div>
  );
}

export default App;

```

## Configuration

To config the library you have set somes keys. For this you need to use `useConfig` hook.

NOTE: The vaid ENVIRONMENT values are: `DEVELOP`, `STAGING`, `UAT` and `PROD`

#### Web Configuration type

```
{
  CLIENT: string;
  SECRET_KEY: string;
  ENABLE_TF_AUTHENTICATION: boolean;
  ENVIRONMENT: Env;
  TIMEOUT: number;
  TF_SSO_CLIENT: string;
  TF_SSO_SECRET: string;
}
```

#### Example

```js
import { useConfig } from '@manacommon/web-auth';

const App = () => {
  const { setConfiguration } = useConfig();

  useEffect(() => {
    setConfiguration({
      ENVIRONMENT: 'your_environment_name', // DEVELOP - STAGING - UAT - PROD. Default value: DEVELOP
      TF_SSO_CLIENT: 'your_TF_client_key', // Default value: empty
      TF_SSO_SECRET: 'your_TF_secret_key', // Default value: empty
      SECRET_KEY: 'your_secret_key', // Default value: empty
      CLIENT: 'your_client_key', // Default value: empty
      ENABLE_TF_AUTHENTICATION: true, // Enables or disables the ticket fairy authentication - Default value: true
    });
  }, [setConfiguration]);

  return (
    // Here you should render your app
  );
};
```

## Documentation

- [Components](#components)
- [Hooks](#hooks)

## <a id="components">Components</a>

- [SignUp](#signup)
- [CreatePassword](#create-password)
- [VerificationCode](#verification-code)
- [Welcome](#welcome)
- [ForgotPassword](#forgot_password)
- [Login](#login)
- [LoginWithEmail](#login_with_email)
- [OnBoarding](#on_boarding)

### <a id="signup">SignUp</a>

Component with form to sign up a new user. Fields:

- Name
- Lastname
- Email
- Password
- Confirm Password

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-signup.png"  width="400">

#### Props

| Name                      | Type                      | Required | Default       | Description                                                                                                                                                                          |
| ------------------------- | ------------------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| onSubmit                  | () => void                | true     | -             | Function to execute after signup proccess end.                                                                                                                                       |
| showLogo                  | boolean                   | false    | true          | Indicates whether to display the mana logo                                                                                                                                           |
| errors                    | object                    | false    | -             | Object to store errors                                                                                                                                                               |
| onNavigateSignIn          | () => void                | false    | -             | Function to navigate to the sign-in page                                                                                                                                             |
| onClickTerms              | () => void                | false    | -             | Function to handle the click event for terms                                                                                                                                         |
| styles                    | object                    | false    | defaultStyles | Custom styles objects                                                                                                                                                                |
| onError                   | (error:any) => void       | false    | -             | Function to handle errors                                                                                                                                                            |
| onChangeData              | (data: IFormData) => void | false    | -             | Function to handle data change                                                                                                                                                       |
| externalRegisterEmailLink | string                    | true     | -             | External link to add on email confirmation. Should be url that contains the ActivateAccount component or another screen that calls the activate endpoint exported on useSignUp hook. |
| texts                     | object                    | false    | defaultTexts  | Custom texts object                                                                                                                                                                  |

```javascript
interface IFormData {
  name: string;
  lastName: string;
  email: string;
  password: string;
  confirmPassword: string;
}

interface ISignUpProps {
  showLogo?: boolean;
  onSubmit: () => void;
  onError?: (error: any) => void;
  /**
   * Errors object with this keys:
   * - name
   * - lastName
   * - email
   * - password
   * - confirmPassword
   */
  errors?: IFormData;
  /**
   * Navigation to sign in screen
   */
  onNavigateSignIn?: () => void;
  /**
   * Action or navigations to execute after pres on EULA terms
   */
  onClickTerms?: () => void;
  /**
   * Custom styles to diferents sections
   */
  styles?: {
    container?: CSSProperties,
    title?: CSSProperties,
    subtitle?: CSSProperties,
    formContainer?: CSSProperties,
    inputsContainer?: CSSProperties,
    terms?: CSSProperties,
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    },
    passwordWrapper?: CSSProperties,
  };
  /**
   * Custom texts
   *
   */
  texts?: {
    title: string,
    subTitle: string,
    signIn: string,
    usernameInUse: string,
    invalidPassword: string,
    termsText: string,
    inputName: string,
    inputLastname: string,
    inputEmail: string,
    inputPassword: string,
    inputConfirmPassword: string,
    submitButton: string,
    validations?: {
      characters: string,
      uppercase: string,
      number: string,
      specialCharacter: string,
    },
  };
  onChangeData?: (data: IFormData) => void;
  /**
   *  This links it's added on the verification email.
   *
   *  Should be the url to go back when users press on 'Confirm Email'.
   *
   *  Should be url that contains the ActivateAccount component or another screen
   *  that calls the activate endpoint exported on useSignUp hook.
   */
  externalRegisterEmailLink: string;
  /**
   * Page wrapper options
   */
  showBackButton?: boolean;
  onClickBack?: () => void;
}
```

#### Example

```js
import { SignUp } from "@manacommon/web-auth";
import { useNavigate } from 'react-router';

const SignUpScreen = () => {
    const [showModal, setShowModal] = useState(false);
    const navigate = useNavigate();

    const ExampleModal = () => {
        return <div> "(Terms information here)" </div>
    }

    return (
        <SignUp
            onSubmit={() => navigate("/home")}
            onNavigateSignIn={() => navigate("/sign-in")}
            onClickTerms={() => setShowModal(true)}
            externalRegisterEmailLink={"https://www.exampleweb.com/account_verification"}
            styles={{ container: { padding: 24 } }}
            texts={{ title: "Example title" }}
        />
        <ExampleModal isVisible={showModal} />
    )
}
```

### <a id="create-password">CreatePassword</a>

Components to create a new password with his validations tags under the inputs.
You could use custom or default validations.

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-create-password.png"  width="400">

#### Props

| Name              | Type                                                | Required | Default                            | Description                             |
| ----------------- | --------------------------------------------------- | -------- | ---------------------------------- | --------------------------------------- |
| customValidations | IValidation[]                                       | false    | [defaultValidations](#validations) | Custom validations array                |
| showLogo          | boolean                                             | false    | true                               | Indicates whether to show the mana logo |
| onConfirm         | (password: string, confirmPassword: string) => void | true     | -                                  | Function to handle confirmation         |
| styles            | object                                              | false    | defaultStyles                      | Custom styles object                    |
| texts             | object                                              | false    | defaultTexts                       | Custom texts object                     |

```javascript
interface ICreatePasswordProps {
  customValidations?: IValidation[];
  showLogo?: boolean;
  onConfirm: (password: string, confirmPassword: string) => void;
  texts?: CreatePasswordTexts;
  styles?: {
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    },
    container?: CSSProperties,
    manaLogo?: CSSProperties,
    inputPassword?: CSSProperties,
    inputConfirm?: CSSProperties,
    centerContainer?: CSSProperties,
    button?: CSSProperties,
  };
  email: string;
  code: string;
  /**
   * Page wrapper options
   */
  showBackButton?: boolean;
  onClickBack?: () => void;
}
```

#### <a id="validations">Default Validations</a>

- 1 number
- 1 Uppercase
- 1 Special character
- Length from 7 to 16

#### Example

```js
import { CreatePassword } from '@manacommon/web-auth';
import { useNavigate } from 'react-router';

const CreatePasswordScreen = () => {
  const navigate = useNavigate();
  const validateLength = (value: string) => {
    return value.length >= 7 && value.length <= 16;
  };

  const customValidations = [
    {
      label: '7-16 characters',
      isApproved: false,
      id: 1,
      validationFn: validateLength,
    },
  ];

  const onConfirm = () => {
    navigate('/login');
  };

  return (
    <CreatePassword
      onConfirm={onConfirm}
      customValidations={customValidations}
      styles={{ inputConfirm: { paddingTop: 16 } }}
      texts={{
        placeholders: {
          password: 'Enter password',
          confirmPassword: 'Enter password confirmation',
        },
      }}
    />
  );
};
```

### <a id="verification-code">VerificationCode</a>

Component with N fields to enter the verification code sended to email. The default length is 4.

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-verification-code.png"  width="400">

#### Props

| Name          | Type       | Required | Default       | Description                                            |
| ------------- | ---------- | -------- | ------------- | ------------------------------------------------------ |
| onClickResend | () => void | false    | undefined     | Function to handle click event for resend email action |
| showLogo      | boolean    | false    | true          | Indicates whether to display the mana logo             |
| onComplete    | () => void | true     | -             | Function to handle click on complete button            |
| styles        | object     | false    | defaultStyles | Custom styles object                                   |
| texts         | object     | false    | defaultTexts  | Custom texts object                                    |
| codeLength    | number     | false    | 4             | Length of the code for verification                    |

```javascript
interface IVerificationCodeProps {
  showLogo?: boolean;
  onClickResend?: () => void;
  onComplete: (code: string) => void;
  codeLength?: number;
  styles?: {
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    }
    container?: CSSProperties,
    manaLogo?: CSSProperties,
    centerContainer?: CSSProperties,
    codeContainer?: CSSProperties,
    link?: CSSProperties,
    title?: CSSProperties,
  };
  texts?: {
    title?: string,
    linkFirstText?: string,
    linkSecondText?: string,
  };
  userEmail: string;
}
```

#### Example

```js
import { VerificationCode } from '@manacommon/web-auth';
import { useNavigate } from 'react-router';

const CreatePasswordScreen = () => {
  const navigate = useNavigate();
  const validateLength = (value: string) => {
    return value.length >= 7 && value.length <= 16;
  };

  const onComplete = () => {
    navigate('/login');
  };

  return (
    <VerificationCode
      onComplete={onComplete}
      codeLength={5}
      styles={{ title: { color: 'red' } }}
      texts={{ title: 'New title' }}
    />
  );
};
```

### <a id="welcome">Welcome</a>

Render a loader and call the function to activate account. After a seconds show a welcome message or an
error if the request fail.

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-welcome.png"  width="400">

#### Props

| Name                   | Type                                 | Required | Default       | Description                |
| ---------------------- | ------------------------------------ | -------- | ------------- | -------------------------- |
| onCompleteVerification | (data: IApiConfirmEmailData) => void | true     | -             | Receive username and token |
| styles                 | object                               | false    | defaultStyles | Custom styles object       |
| texts                  | object                               | false    | defaultTexts  | Custom texts object        |

```javascript
interface IWelcomeProps {
  texts?: WelcomeTexts;
  styles?: {
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    },
    container?: CSSProperties,
    icon?: CSSProperties,
    title?: CSSProperties,
  };
  onCompleteVerification: (data: IApiConfirmEmailData) => void;
}
```

#### Example

```js
import { Welcome } from '@manacommon/web-auth';
import { useNavigate } from 'react-router';

const CreatePasswordScreen = () => {
  const navigate = useNavigate();

  const handleCompleteVerification = (data: IApiConfirmEmailData) => {
    // data information :
    //   - token: string;
    //   - refreshToken: string;
    //   - username: string;
    //   - isLockedOut: boolean;
    //   - isNotAllowed: boolean;

    console.log('This is the token to save -> ', data.token);
  };

  return <Welcome onCompleteVerification={handleCompleteVerification} />;
};
```

### <a id="forgot_password">ForgotPassword</a>

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-forgot-password.png"  width="400">

#### Props

| Name        | Type                           | Required | Default       | Description                               |
| ----------- | ------------------------------ | -------- | ------------- | ----------------------------------------- |
| onSendEmail | (emailOrPhone: string) => void | true     | -             | Function to execute after email is sended |
| styles      | object                         | false    | defaultStyles | Custom styles object                      |
| texts       | object                         | false    | defaultTexts  | Custom texts object                       |

```javascript
interface IForgotPasswordProps {
  onSendEmail: (emailOrPhone: string) => void;
  styles?: {
    centerContainer?: CSSProperties,
    input?: CSSProperties,
    button?: CSSProperties,
    root?: CSSProperties,
  };
  texts?: ForgotPasswordTexts;
  /**
   * Page wrapper options
   */
  showBackButton?: boolean;
  onClickBack?: () => void;
}
```

#### Example

```js
import { ForgotPassword } from '@manacommon/web-auth';
import { useNavigate } from 'react-router';

const ForgotPasswordScreen = () => {
  const navigate = useNavigate();

  const handleOnSendEmail = (emailOrPhone: string) => {
    // You have to navigate to verification code screen
    navigate('/verification_code');
  };

  return <ForgotPassword onSendEmail={handleOnSendEmail} />;
};
```

### <a id="login">Login</a>

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-login.png"  width="400">
#### Props

| Name                 | Type                          | Required | Default       | Description                                                                    |
| -------------------- | ----------------------------- | -------- | ------------- | ------------------------------------------------------------------------------ |
| handleLoginWithEmail | () => void                    | false    | -             | Function to navigate to login with email screen                                |
| handleSignUp         | () => void                    | true     | -             | Function navigate to sign up                                                   |
| onLoginSuccess       | (data: ILoginResult ) => void | false    | -             |
| onLoginFail          | (error: any) => void          | false    | -             | -                                                                              |
| styles               | object                        | false    | defaultStyles | Custom styles object                                                           |
| texts                | object                        | false    | defaultTexts  | Custom texts object                                                            |
| enabledProviders     | object                        | false    | -             | Used to custom enable or disable the external logins                           |
| redirectUri          | string                        | false    | -             | Used internaly by LoginButtons to add a custom redirection for external logins |

```javascript
interface ILoginProps {
  handleLoginWithEmail?: () => void;
  handleSignUp?: () => void;
  onLoginSuccess?: (data: ILoginResult | undefined) => void;
  onLoginFail?: (error: any) => void;
  texts?: LoginTexts;
  redirectUri?: string;
  enabledProviders?: IEnabledLogins;
  styles?: {
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    }
    loginWrapper?: CSSProperties,
    footer?: CSSProperties,
  };
}
```

#### Example

```js
import { Login } from '@manacommon/web-auth';
import { useNavigate } from 'react-router';

const LoginScreen = () => {
  const navigate = useNavigate();

  const handleGoToLoginWithEmail = () => {
    navigate('/login_with_email');
  };

  const handlegoToSignUp = () => {
    navigate('/sign_up');
  };

  return (
    <Login
      handleLoginWithEmail={handleGoToLoginWithEmail}
      handleSignUp={handlegoToSignUp}
    />
  );
};
```

### <a id="login_with_email">LoginWithEmail</a>

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/readme-login-email.png"  width="400">
#### Props

| Name             | Type                           | Required | Default       | Description                                         |
| ---------------- | ------------------------------ | -------- | ------------- | --------------------------------------------------- |
| onLoginSuccess   | (result: ILoginResult) => void | false    | -             | Function to execute after request success           |
| onLoginError     | (error: any) => void           | false    | -             | Function to execute if request fail                 |
| onForgotPassword | () => void                     | false    | -             | Function to execute when the user press in the link |
| onSignUp         | () => void                     | false    | -             | Function to execute when the user press in the link |
| styles           | object                         | false    | defaultStyles | Custom styles object                                |
| texts            | object                         | false    | defaultTexts  | Custom texts object                                 |

```javascript
interface LoginWithEmailProps {
  onLoginSuccess?: (result: OnLoginSuccess) => void;
  onLoginError?: (error: any) => void;
  onForgotPassword?: () => void;
  onSignUp?: () => void;
  texts?: LoginWithEmailTexts;
  styles?: {
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    },
    loginBoxWrapper?: CSSProperties,
    inputWrapper?: CSSProperties,
    footer?: CSSProperties,
  };
  /**
   * Page wrapper options
   */
  showBackButton?: boolean;
  onClickBack?: () => void;
}
```

#### Example

```js
import { LoginWithEmail } from '@manacommon/web-auth';
import { useNavigate } from 'react-router';

const LoginWithEmailScreen = () => {
  const navigate = useNavigate();

  const onLoginSuccess = (result: ILoginResult) => {
    // results information:
    //  - tfAccessToken?: string;
    //  - tfRefreshToken?: string;
    //  - tfScope?: string;
    //  - tfTokenType?: string;
    //  - userInformation: IApiUserInformation;

    navigate('/home');
  };

  const onLoginError = (error: any) => {
    console.log('Login error: ', error);
  };

  return (
    <LoginWithEmail
      onLoginError={onLoginError}
      onLoginSuccess={onLoginSuccess}
    />
  );
};
```

### <a id="on_boarding">OnBoarding</a>

<img src="https://mana-static-files.s3.amazonaws.com/mana-library/doc-images/on_boarding_example.png">

#### Props

```javascript
interface IOnBoardingProps {
  userId: string;
  texts?: OnBoardingTexts;
  initialStepConfig?: {
    step: OnBoardingStep,
    cityId?: number,
  };
  styles?: {
    root?: {
      container?: CSSProperties,
      header?: CSSProperties,
      backButtonWrapper?: CSSProperties,
      logoWrapper?: CSSProperties,
    },
  };
  onNext?: () => void;
  onPrevious?: () => void;
  onComplete?: () => void;
}
```

#### Example

```js
import { OnBoarding } from '@manacommon/web-auth';

const OnBoardingExample = () => {
  const [userLogged, setUserLogged] = useState<UserInformation>();

  useEffect(()=> {
    /**
     * You can get the user information from the verificate account or any login component
     */
  })

  return (
    <OnBoarding
      userId={userLogged?.id ?? ''}
      onComplete={() => console.log('on boarding completed!')}
    />
  );
};
```

## <a id="hooks">Hooks</a>

- [useSignUp](#useSingUp)
- [useAuthentication](#useAuth)

### <a id="useSingUp">useSignUp</a>

#### signUp

Function to sign up a new user. Receives:

| Parameter                 | Type    |
| ------------------------- | ------- |
| lastname                  | string  |
| name                      | string  |
| username                  | string  |
| password                  | string  |
| roleName                  | Roles   |
| externalRegister          | boolean |
| externalRegisterEmailLink | string  |

#### Example

```js
import { RegisterErrors, Roles } from '@manacommon/core/src/models';
import { useSignUp } from '@manacommon/core/src/hooks';

const { signUp } = useSignUp();

const handleError = (error: any): void => {
  if (error.response.data.errorCode === RegisterErrors.USERNAME_IN_USE) {
    // Actions if email exist
  }
  // Other actions to handle error
};
const handleSignUp = async (): Promise<void> => {
  try {
    await signUp({
      lastname: 'Smith',
      name: 'Arnold',
      username: 'asmith@gmail.com',
      password: 'Qwerty1234.',
      roleName: Roles.Guest,
      externalRegister: true,
      externalRegisterEmailLink:
        'https://www.exampleweb.com/account_verification',
    });
    // On succes actions goes here
  } catch (e: any) {
    handleError(e);
  }
};
```

#### confirmEmail

Function to confirm validation from email. Receives:

| Parameter | Type   |
| --------- | ------ |
| userId    | string |
| token     | string |

#### Example

```js
import { Loader } from '@manacommon/web';
import { useSignUp } from '@manacommon/core/src/hooks';

const WelcomeScreen = () => {
  const [isLoading, setIsLoading] = useState(true);
  const { confirmEmail } = useSignUp();
  const urlParams = new URLSearchParams(window.location.search);
  // Get user id by url
  const userId = urlParams.get('userId');
  // Get token by url
  const token = urlParams.get('verificationToken');

  useEffect(() => {
    const completeRegister = async (): Promise<void> => {
      if (userId !== null && token !== null) {
        try {
          const data = await confirmEmail(userId, token);
          setIsLoading(false);
        } catch {
          setIsLoading(false);
        }
      }
    };

    void completeRegister();
  }, [userId]);

  {
    isLoading ? <Loader /> : <div>{/* Welcome information goes here */}</div>;
  }
};
```

### <a id="useAuth">useAuthentication</a>

#### Functions and params

```javascript
export interface IExternalAuthRequest {
  provider: ApiExternalLoginProviders;
  idToken?: string;
  name?: string;
  lastName?: string;
  accessToken?: string;
}

export interface IUseAuthentication {
  getLoggedUserData: () => Promise<UserInformation>;
  handleLogin: (
    email: string,
    password: string,
    onSuccess?: (result: ILoginResult) => void,
    onError?: (error: any) => void,
  ) => Promise<ILoginResult | undefined>;
  handleLoginExternal: (
    request: IExternalAuthRequest,
    onSuccess?: (userInfo: any) => void,
    onError?: (error: any) => void,
  ) => Promise<ILoginResult | undefined>;
  sendForgotPasswordEmail: (emailOrPhone: string) => Promise<void>;
  checkValidCode: (email: string, code: string) => Promise<boolean>;
  changePassword: (
    email: string,
    code: string,
    password: string,
  ) => Promise<boolean>;
}
```

#### Import and use example

```javascript
import useAuthentication from '@manacommon/web-auth';

const { handleLogin } = useAuthentication();
```

#### Login example

```javascript
const handleLoginSuccess = (response: ILoginResult) => {
  // Do what do you need with the response
};

handleLoginError = (error: any) => {
  // Handle login error here
};

const handleSubmit = async (email: string, password: string): Promise<void> => {
  await handleLogin(email, password, handleLoginSuccess, handleLoginError);
};
```

#### Login external example

```javascript
const handleExternalLogin = async (
  /*
   * Have to be access_token for google or id_token for facebook and apple.
   * You will get this data from <SocialButtons/> callbacs
   */
  token: string,
  provider: ApiExternalLoginProviders, // GOOGLE - FACEBOOK - APPLE
  onLoginSuccess?: (data: ILoginResult | undefined) => void,
  onLoginFail?: (error: any) => void,
): Promise<ILoginResult | undefined> => {
  const request: IExternalAuthRequest = { provider };

  if (provider === 'FACEBOOK' || provider === 'apple') {
    request.idToken = token;
  } else {
    request.accessToken = token;
  }

  try {
    const result = await handleLoginExternal(request);
    if (onLoginSuccess) {
      onLoginSuccess(result);
    }
    return result;
  } catch (error) {
    if (onLoginFail) {
      onLoginFail(data);
    }
  }
};
```

## Troubleshooting

- If you have created your project using CRA, maybe get a warning about babel in the console. In that case you can add this ` "@babel/plugin-proposal-private-property-in-object": "^7.21.11"`` as  `dev dependency` to avoid it.

## Change Log

### Version 1.0.4

- Documentation update
- Fixed issue with `isSafari` check
- Fixed `PageWrapper` style property not being passed in `Login` component
- Fixed `PageWrapper` style property not being passed in `ForgotPassword` component
- Fixed `PageWrapper` style property not being passed in `SignUp` component
- Fixed `LoginWithEmail` style property not being passed for login box and login box footer

### Version 1.0.5

- Update Documentation
- Fixed configuration environment values
- Updated config prop names for `setConfiguration`. (see documentation)
- Updated root custom styles for: `Login`, `OnBoarding`, `ValidateAccount`, `VerificationCode`, `Welcome`, `LoginWithEmail`, `CreatePassword`, `ForgotPassword` and `SignUp` components. Now the type is `IPageWrapperCustomStyle` instead of `CSSProperties`. (see documentation)
- Fixed goback in onboarding
- Now `LoginWithEmail`, `CreatePassword`, `ForgotPassword` and `SignUp` components has a showBackButton flag and onClickBack callback. (See documentation)
- Add new default validation messages for: `LoginWithEmail`, `SignUp` and `CreatePassword` components. (see documentation)

### Version 1.0.6

- ForgotPassword: param to add title styles
- LoginWithEmail: param to add title styles
- Disabled button bug fixed

### Version 1.0.7

- Fixed login-config params for useAuthentication hook

### Version 1.0.8

- We update @manacommon/core in order to add tfResponseHeaders to onLoginSuccess callbacks