> For the complete documentation index, see [llms.txt](https://docs.dataswyft.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dataswyft.com/build/getting-started/react-pda/5.-component-pages.md).

# 5. Component Pages

### Create Signup Page

In the same way with the Login page, we can create a page for the registration.

For the registration, we need to collect the username and the email, and redirect to the Hatters to complete the registration.

Lets create the **SignupPage.js** in the **Signup** feature folder:

```javascript
// src/features/Signup/SignupPage.js
import React, { useState } from 'react';
import { appConfig } from '../../app.config';
import { isEmail, isHatName } from '../../utils/validations';

function SignupPage() {
    const initUser = {
        username: '',
        email: '',
    };

    const [user, setUser] = useState(initUser);
    const [errorMsg, setErrorMsg] = useState('');

    const errorMessages = {
        usernameNotValid: 'Sorry, this username is not valid',
        emailNotRecognised: 'Sorry, email is not valid',
    };

    const navigateToHatters = () => {
        const redirectUrl = `http://${window.location.host}/authentication`;
        const applicationId = appConfig.applicationId;

        window.location.href = `https://hatters.dataswift.io/services/baas/signup?email=${user.email}&hat_name=${user.username}&application_id=${applicationId}&redirect_uri=${redirectUrl}&lang=en`;
    };

    const handleChange = event => {
        const name = event.target.name;
        const value = event.target.value;

        setUser({ ...user, [name]: value });
        setErrorMsg('');
    };

    const handleSubmit = event => {
        event.preventDefault();
        validateSignupDetails();
    };

    const validateSignupDetails = () => {
        let errorMsg = '';

        if (!isHatName(user.username)) {
            errorMsg = errorMessages.usernameNotValid;
        } else if (!isEmail(user.email)) {
            errorMsg = errorMessages.emailNotRecognised;
        } else {
            navigateToHatters();
        }

        if (errorMsg) {
            setErrorMsg(errorMsg);
        }
    };

    return (
        <form onSubmit={e => handleSubmit(e)} className={'flex-column-wrapper flex-content-center flex-align-items-center'}>
            <div className={'flex-spacer-small'} />

            <h3>Create Account</h3>
            <div className={'flex-spacer-small'} />

            <input
                className={` ${errorMsg ? 'input-error-field' : null}`}
                name={'username'}
                type={'text'}
                placeholder="Username"
                autoComplete={'username'}
                value={user.username}
                onChange={e => handleChange(e)}
            />
            <input
                className={` ${errorMsg ? 'input-error-field' : null}`}
                name={'email'}
                type={'text'}
                placeholder="Email"
                autoComplete={'email'}
                value={user.email}
                onChange={e => handleChange(e)}
            />
            {errorMsg && <div className={'input-error-label'}>{errorMsg}</div>}

            <div className={'flex-spacer-large'} />

            <button className={'btn btn-accent'} type={'submit'}>
                Next
            </button>

            <div className={'flex-spacer-small'} />
        </form>
    );
}

export default SignupPage;
```

In the **validations.js** file, include a function to check if the email is valid:

```javascript
// src/utils/validations.js
const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

export const isEmail = email => {
  return EMAIL_REGEX.test(email);
};
```

Include the "/signup" route in the **Routing.js**:

```javascript
// src/app/Routing.js
function Routing() {
    return (
        <Router>
            <Header />
            <Switch>
                <Route exact path="/" component={HomePage} />
                <Route path="/login" component={LoginPage} />
                <Route path="/signup" component={SignupPage} />
                <Route path="/authentication" component={AuthenticationHandler} />
            </Switch>
        </Router>
    );
}

export default Routing;
```

### Create a private Route for the authenticated username

In this case, we need to create a "global" state to keep information for the current authenticated user. With the [Context](https://reactjs.org/docs/context.html) we can create a simple state share across all the components.

We'll need to keep information such as a flag to check if the user is authenticated, the [JWT](https://jwt.io) token, and the username.

```javascript
state = {
    user: {
      isAuthenticated: false,
      token: '',
      hatName: '',
    },
  }
```

Firstly, we have to create the Context object. Create the **AuthContext.js** file in the **context** folder under the **components/** folder:

```
// src/components/context/AuthContext.js
import React from 'react';

const AuthContext = React.createContext();

export default AuthContext;
```

Secondly, create the Context Provider with state and helper function to log in/out. Create the **AuthProvider.js**:

```
// src/components/context/AuthProvider.js
import React, { Component } from 'react';
import AuthContext from './AuthContext';
import { HatTokenValidation } from '@dataswift/hat-js/lib/utils/HatTokenValidation';

export class AuthProvider extends Component {
  state = {
    user: {
      isAuthenticated: false,
      token: '',
      hatName: '',
    },
  };

  render() {
    return (
      <AuthContext.Provider
        value={{
          user: this.state.user,
          logout: () => {
            sessionStorage.removeItem('token');

            this.setState({
              user: {
                isAuthenticated: false,
                token: '',
                hatName: '',
              },
            });
          },
          login: (token, hatName) => {
            if (token && !HatTokenValidation.isEncodedTokenExpired(token)) {
              this.setState({
                user: {
                  isAuthenticated: true,
                  token: token,
                  hatName: hatName,
                },
              });
            }
          },
        }}
      >
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}
```

#### Include AuthProvider in the App component

```javascript
// src/app/App.js
import { AuthProvider } from "../components/context/AuthProvider";

function App() {
  return (
      <AuthProvider>
        <div className="app">
          <Routing/>
        </div>
      </AuthProvider>
  );
}
```

#### Check if the user is authenticated

Now, in the Home page, we can check if the user is authenticated and display a protected page. In order to see this private page, they must login first.

HAT-JS offers the option to import the HatTokenValidation class to help decode the token, accessing the [JWT](https://jwt.io)'s properties and check the token expiration time:

```
// src/features/Home/HomePage.js
import React, { useEffect, useContext } from 'react';
import './HomePage.scss';
import { HatTokenValidation } from '@dataswift/hat-js/lib/utils/HatTokenValidation';
import AuthContext from "../../components/context/AuthContext";
function HomePage() {
  const authContext = useContext(AuthContext);

  useEffect(() => {
    const token = sessionStorage.getItem('token');

    if (token) {
      const decodedToken = HatTokenValidation.decodeToken(token);

      // If the token has not expired, log in the user.
      if (!HatTokenValidation.isExpired(decodedToken)) {
        authContext.login(token, decodedToken.iss);
      }
    }
  }, []);

  return (
    <AuthContext.Consumer>
      {context => (
        <>
          <div className="home-wrapper">{context.user.isAuthenticated && <div>Authenticated!</div>}</div>
        </>
      )}
    </AuthContext.Consumer>
  );
}

export default HomePage;
```

#### Add a logout button

In the Header.js we can use the **AuthContext** and display the "Logout" button when the user is authenticated:

```javascript
// src/components/header/Header.js
import React from 'react';
import { Link, NavLink } from 'react-router-dom';
import './Header.scss';
import AuthContext from '../context/AuthContext';

function Header() {
    return (
        <AuthContext.Consumer>
            {context => (
                <>
                    <header className="header">
                        <NavLink exact activeClassName="active" to="/">
                            Home
                        </NavLink>

                        {context.user.isAuthenticated && (
                            <Link to="/login" onClick={() => context.logout()}>
                                Log out
                            </Link>
                        )}

                        {!context.user.isAuthenticated && (
                            <ul>
                                <li>
                                    <NavLink activeClassName="active" to="/login">
                                        Log in
                                    </NavLink>
                                </li>
                                <li>
                                    <NavLink activeClassName="active" to="/signup">
                                        Create account
                                    </NavLink>
                                </li>
                            </ul>
                        )}
                    </header>
                </>
            )}
        </AuthContext.Consumer>
    );
}
export default Header;
```

### Create a protected Home component

The next step is to create the protected Home component. Lets create the **HomePrivate.js** file into the Home feature:

```
// src/features/Home/HomePrivate.js
import React from 'react';

function HomePrivate() {
    return (
        <div className="home-private">
            <div className="container">
                <div className="content">
                    Private content
                </div>
            </div>
        </div>
    );
}

export default HomePrivate;
```

And include this CSS in the **HomePage.scss**:

```
// src/features/Home/HomePage.scss
.
.

.home-private {
    height: 100%;
    width: 100%;

    .container {
        border-radius: 6px;
        padding: 2.4rem;
    }

    .content {
        background: #e9e9e9;
        padding: 2.4rem;
        border-radius: 6px;
    }
}
```

And then, replace the **\Authenticated!\\\</div>** with the component:

```
// src/features/Home/HomePage.js
.
.
import HomePrivate from "./HomePrivate";

function HomePage() {
  .
  .

  return (
    <AuthContext.Consumer>
      {context => (
        <>
          <div className="home-wrapper">{context.user.isAuthenticated && <HomePrivate />}</div>
        </>
      )}
    </AuthContext.Consumer>
  );
}

export default HomePage;
```

### Create Notes component

Create a new folder **Notes** in the **features/** with the **Notes.js** file:

```javascript
// src/features/Notes/Notes.js
import React from 'react';
import './Notes.scss';

function Notes() {

    return (
        <form
            className={'notes-wrapper flex-column-wrapper flex-content-center flex-align-items-center'}
        >
            <div className={'flex-spacer-small'} />
            <h3>Save a note on your HAT</h3>
            <input
                name={'note'}
                type={'text'}
                placeholder="Remember to..."
                autoComplete={'text'}
            />
            <div className={'flex-spacer-small'} />
            <button className={'btn btn-accent'} type={'submit'}>
                Save
            </button>
            <div className={'flex-spacer-small'} />
        </form>
    );
}

export default Notes;
```

And the **Notes.scss**:

```css
// src/features/Notes/Notes.scss
.notes-wrapper {
  input {
    margin-top: 2.5rem;
    margin-bottom: 2.5rem;
  }
}

.note-row-wrapper {
  display: flex;
  flex-direction: row;
  margin-top: 1rem;

  .note-content {
    text-align: left;
    flex: 1 1;
    color: #4a556b;
    font-size: 1.6rem;
  }

  button {
    margin-left: 1rem;
  }
}

.notes-list {
  margin-top: 2.5rem;
  width: 100%;
  max-width: 32rem;
  list-style-type: none;
}
```

Include the Notes component in the **HomePrivate.js**:

```javascript
// src/features/Home/HomePrivate.js
import React from 'react';
import Notes from "../Notes/Notes";

function HomePrivate() {
    return (
        <div className="home-private">
            <div className="container">
                <div className="content">
                    <Notes />
                </div>
            </div>
        </div>
    );
}

export default HomePrivate;
```
