ArgentBank
I work as a Front-End Developer at the Remede Agency, a web agency. We are developing a full-stack app for a new bank company, ArgentBank.
TYPE | Web, Education |
DATE | |
STACK | React, React-router, Redux-toolkit (RTK), RTK-query, Formik, Toastify, Yup, Swagger |
This project is the n°13 of the OpenClassrooms Front-End learning path.
The problem
Argent Bank is a new bank that is starting up. She’s trying to break into the industry and needs help setting up her app. It needs a web application that allows customers to log in and manage their accounts and profile.
The solution
- Build a responsive React App
- Add an authentication system with Redux, according to User Stories.
- Document the new endpoints of the API with Swagger
1. Responsive Web App
2. Authentication system
Vertical Architecture
Using Redux ToolKit, I followed some vertical architecture’s principles : a slice per feature.
├── 📂 app
│ ├── apiSlice.js
│ ├── App.jsx
│ └── store.js
├── 📂 features
│ ├── authSlice.js
│ └── userSlice.js
├── 📂 pages
│ ├── 📂 Error404
│ ├── 📂 Home
│ ├── 📂 Layout
│ ├── 📂 Login
│ └── 📂 Profile
└── 📂 styles
└── *.scss
Private Route
The first step of authentication was to add a private route with React-Router
. The idea is to provide a conditional routing system which renders the Profile page if the user is logged or the Login page instead.
const PrivateRoute = ({ element }) => {
const token = useSelector(selectCurrentToken);
return token ? element : <Navigate to="/login" replace={true} />;
};
const App = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ index: true, element: <Home /> },
{ path: 'login', element: <Login /> },
{ path: 'profile', element: <PrivateRoute element={<Profile />} /> },
{ path: '*', element: <Error404 /> },
],
},
]);
Form Validation
The form validation was handled by Formik
and Yup
. A visual feedback from Toastify
was added to provide a great user experience.
const validationSchema = Yup.object({
email: Yup.string().email('Invalid email addresss').required('Required'),
password: Yup.string()
.min(8, 'Must be 8 characters or more')
.max(20, 'Must be 20 characters or less')
.required('Required'),
rememberMe: Yup.boolean().default(false),
});
const initialValues = { email: '', password: '', rememberMe: false };
return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
<Form>
<TextInput label="Email" name="email" type="email" />
<TextInput label="Password" name="password" type="password" />
<Checkbox name="rememberMe">Remember me</Checkbox>
<button className={styles.button} type="submit">
Submit
</button>
</Form>
</Formik>
);
RTK
When the form was successfully submitted, RTK stores a token from the server and use it in the Header of every API requests.
export const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:3001/api/v1',
prepareHeaders: (headers, { getState }) => {
const token = getState().auth.token || localStorage.getItem('token');
if (!headers.has('Authorization') && token) {
headers.set('Authorization', `Bearer ${token}`);
}
return headers;
},
}),
});
3. Documentation of the API
We used Swagger to add API endpoints in the documentation
/transactions/{transactionId}:
get:
security:
- Bearer: []
tags:
- Transaction Module
summary: Find transaction's details by id
description: Find transaction's details by id (jwt token)
parameters:
- in: header
name: Authorization
description: Attach Bearer JWT token
required: true
type: string
What I Learned
- Authenticate to an API
- Model an API
- Interact with an API
- Implement a state manager in a React application
👉 I’ve written also two articles on LinkedIn and Github/gists about RTK: