Optera, a consulting company in Brazil, reached out to us with a challenge that would test our technical capabilities and provide us with the opportunity to show what we are capable of as the first client to order a full-stack project, a project which materializadora successfully delivered in only 3 months.
The application started as an idea to improve the interaction between Optera and its clients, a simple help desk system that would provide a bridge between the two. Even though the initial goal was to build an MVP, such a bridge would have to be well built nonetheless, so for that reason, and also as an opportunity to challenge ourselves, we decided to set a high standard for the technical aspects of the project and treat it not as an MVP but as a full-fledged scalable project ready for production.
For our technical stack in the front-end we chose:
- TypeScript – Language used for the project.
- Next.js – React Framework.
- Ant Design – Design system / Components lib.
- Styled-Components – CSS-in-JS solution.
- Redux Toolkit – Global state & services/API management.
- Socket.io – Websocket lib used for messaging.
And for the back-end:
- Express.js – Web app framework for Node.js.
- MongoDB – Document-oriented Database.
- Atlas Cloud – Cloud Storage for MongoDB
- JWT – Authentication/Encryption.
- Mongoose – Makes dealing with MongoDB easier.
- bcrypt – Password hashing lib.
- body-parser – Node.js body parsing middleware.
- multer – Node.js multipart file upload middleware.
- Socket.io – Websocket lib used for messaging.
The testing was done through Postman’s Newman command-line tool. Our idea was to integrate it with Gitlab CI but unfortunately, we couldn’t figure out how to set up a MongoDB image with a pre-set collections alongside Node.js and Newman. Something we will investigate how to do in the future. For this project, however, even though we wanted to figure out how to implement proper CI, the client said that, since it’s an MVP, they were already satisfied with just being able to run the tests locally, and asked us to set it aside as a future challenge.
The conceptualization of the backend model consisted of:
- Three types of users: Admin, Company and Helpdesk
- Chats (representing support tickets)
- Categories (to filter and organize the chats)
Each user type would have different features of the backend available to them, a Company user, for instance, shouldn’t be able to create a Category or edit other users. Such endpoints and methods should only be available for admin users. To perform such authentication and permissioning we decided to use JWT.
Each Chat has its own category and instead of having the Chat as the host of the messages, each Message is linked to its own chat, a more scalable approach to document-based DBs.
Let’s start with the Login:
(To better showcase the application on materializadora‘s website I took the liberty to translate the application from Portuguese to Spanish).
Quite a simple Login, but at first we had some difficulties implementing it since we had no experience with Redux Toolkit (RTK) and RTK Query. It even led me to open up a question on StackOverflow about how to call endpoints sequentially with RTK Query and React Hooks.
After login in, we’re presented with the dashboard screen where you can see all the open and closed support tickets. For demonstration purposes, I created four categories. Categories which in a real scenario would represent the sectors in which Optera provides support for in their customer companies. We’ll take a look at categories further down the line.
When a company user is created, a helpdesk user is automatically assigned as the responsible user for all the support tickets that that user might open. So when a company user opens up a new ticket some things happen:
- The helpdesk technician who is responsible for the user is automatically assigned to the ticket.
- The ticket is given a title according to the name of the user/company and the number of tickets the user has previously opened in that category.
- An automated message is sent in the chat according to the predefined default message that each category has.
- A preview of the last message sent in the chat becomes available on the dashboard
- The support ticket is marked as “yet to be resolved”.
We can preview the automated message then see it in blue when we open up the chat. This message is sent by a default user set on the backend who’s designated to be the messaging bot for the application.
A helpdesk user can then see the newly created support ticket in his dashboard and access the chat to exchange information with the company that opened it.
All types of files are supported but only images are previewable.
Our major challenge with this feature was to ensure that the chat with Socket.io was well-tied together like the REST endpoints. When we started the development of the chat, we already had a pretty well-rounded validation and error handling suite for the express endpoints composed of middlewares and utils. So to create the messaging system and file transfer, we gave a lot of focus to things like validation and error handling within the Socket.io calls.
Here we can see the categories for each type of ticket, the usage is completely arbitrary, you could have a myriad of different types of tickets.
Currently, there’s no category creation feature in the front-end as the client told us it was not necessary for an MVP feature, nevertheless, there are endpoints and Socket.io events that cover the entire application, so category creation is possible through Postman.