Rev
notion image

Short Explanation

Sistem Informasi Bima Bakery, Made for the Final Project of Software Project Management. SiBaBe is an e-commerce website to buy products (in this case bread) from Bima Bakery.

Project Goals

An online shop for ordering products from Bima Bakery, utilizing Next.js for the front end and Golang for the back end.
Here’s what users can do:
  • Register and log in to their account
  • Browse and view products
  • Add products to their shopping cart
  • Search for products using keywords
  • View their shopping cart and adjust the quantity of items
  • Place an order
  • View order history
  • View the details of past orders
  • Leave a review on purchased products.

Tech Stack Used

This project utilizes React with Next.js, Redux for state management, Typescript for strong typing, Mantine for some components, React Toastify for toast components, and Tailwind CSS for styling.

Spotlight

Conventional Commit

In this project, My team and I decided to use conventional commit so the commit message is cleaner and easier to read. I've been using it since I think it is awesome. Also using Vercel, we can practically backtrack to any deployment of the commit.
We also configured it with Husky so the commit message is checked before committing.
notion image

Redux Middleware to Call API

We use a Redux middleware to manage API calls. Our backend has two separate routes for public and private routes, so we have to update the URL if the user is already authenticated. React Toastify is also used to handle promise state when the API is calling.
const apiMiddleware: Middleware = ({ dispatch, getState }) => (next) => (action) => { next(action); if (action.type !== 'API') { return; } const { meta, url, method, data, actionStart, actionSuccess, actionError, upload, } = action; // Adds support to POST and PUT requests with data const dataOrParams = ['GET'].includes(method) ? 'params' : 'data'; if (getState().user?.user?.token) { httpClient.defaults.headers.Authorization = `Bearer ${ getState().user?.user?.token }`; httpClient.defaults.baseURL = API_URL + '/jwt'; } else { httpClient.defaults.baseURL = API_URL; httpClient.defaults.headers.Authorization = null; } // start action dispatch({ type: actionStart, meta }); if (method === 'POST' && upload) { httpClient .post(url, upload) .then((payload) => { dispatch({ type: actionSuccess, meta, payload: payload.data }); }) .catch((error) => { dispatch({ type: actionError, meta, error: error?.response?.data?.metadata, errorHttp: error, }); }); } else { toast.promise( httpClient .request({ url, method, [dataOrParams]: data, headers: { 'Content-Type': 'application/json', }, }) .then((payload) => { dispatch({ type: actionSuccess, meta, payload: payload.data, method, }); return payload; }) .catch((error) => { dispatch({ type: actionError, meta, error: error?.response?.data, errorHttp: error, }); throw error; }), { pending: 'Loading...', success: { render: (data) => { const successData = data.data as AxiosResponse<ApiResponseType>; return `${successData.data.message}`; }, }, error: { render: (error) => { const errorData = error.data as AxiosError<ApiResponseType>; if (errorData.code === 'ERR_NETWORK') return 'Network error'; return `${errorData.response?.data?.errors}`; }, }, } ); } };
Here's an example of how to call an API in this project:
import { AppDispatch } from '@/redux'; export const getProducts = () => (dispatch: AppDispatch) => { dispatch({ url: '/products', method: 'GET', actionStart: 'PRODUCTS_FETCH', actionSuccess: 'PRODUCTS_FETCH_SUCCESS', actionError: 'PRODUCTS_FETCH_ERROR', type: 'API', }); };

The Problems and How I Solved It

This was my first time fully building a system from scratch, and what made it even more exciting was that all of my teammates were new to this field as well. Since it was for my Software Project Management course, we had to dive into all the exciting document-related tasks before getting our hands dirty with the system itself. In this project, we wore multiple hats, playing the roles of both developers and managers.
During this adventure, I even discovered the art of communicating with the backend. Just like everyone else, we also came face-to-face with the notorious CORS problem. But hey, overcoming challenges is part of the thrill! Effective communication and diving into more online resources became the key to finding solutions.
All in all, this experience has been incredibly enjoyable and immensely educational. It has deepened my understanding of how to construct a fully functional application.

Lesson Learned

I learned a lot from this project and course, a lot of great libraries that I use, how to deal with all the management document stuff, how to work together as a team in tech field, and now I quite understand how reading documentation and actually understanding it is really important.
I am now quite comfortable if I have to learn a new library or stack because I know how to efficiently read documentation now