This is the website for online computer store with a set of products to sell, currently with listing of 4 products available with 3 deals but there is an ability to add more products and pricing rules as needed.
This is a Next.js project bootstrapped with create-next-app.
The folder stucture has been revamped to organise components, pages and styles in separate folders for maintainability.
Follow this README for instructions on Basic Requirements, Set Up along with details about the project so that you can understand the technical details and run the application smoothly.
- Basic Requirement
- Setting Up
- Starting the Server
- Running Tests
- Project Overview
- Folder Structure
- UI/UX
- Deployment
This project runs on Next 14 and requires minimum Node version of 18.17.
You can check your version by running the following command
$ node -vIf your version of node is lower than the requirement, you can get the version by downloading directly from the website or by using nvm as detailed in this tutorial.
Once you have the basic requirement set up, make sure you are in the same directory as package.json
You can navigate to the required file by using cd to change into a certain directory
$ cd /directoryor to change out of the current directory
$ cd ..Once you re in the same directory as package.json, run the following command to install the dependencies
$ npm iAfter the installation is done, you should be able to run the development service by using
$ npm run devOpen http://localhost:3000 with your browser to see the result.
There are a total of 31 tests under 9 test suites in the project. You can run these tests by using the test script
$ npm testThe project uses Jest for the tests.
The project is structured with frontend and backend in different folders within the src folder.
The public folder contains all the public assets like images, svgs and icons.
The tests for the project are placed in tests folder mirroring the structure for src folder with each test file ending with .test.js.
models folder has been used to place products.js and pricingRules.js where each model is storing the following data -
products.js- Details about the products including SKU code and image link.pricingRules.js- Details about the available deals. There are 3 types of deals that have been definied in the system.
a. X for Y deal - You get X items of the SKU for the price of Y items. Essentially getting X - Y items of the SKU for free.
b. Bulk Discount - You get a discounted price if you buy more than a set threshold of a particular SKU.
c. Bundle - If you buy a bundled item with the current SKU, you get the bundled item for free. For simplicity, in this project I have displayed this as a discount on the current SKU by bundling.
A database wasn't used because the application itself is rather straightforward, but the project can be extended further to make use of databases if necessary.
utils folder contains the business logic with calculateTotalPriceAndBreakDown.js defining the function to fetch the total price and the breakdown for the cart of items. It's corresponding test is available in tests/utils folder.
pages folder contains the pages for the application, with pages/api containing backend APIs while the other pages are available on top level. The pages are as follows -
-
/api/checkout.js- Contains the backend api for/api/checkoutwhich is aPOSTAPI to fetch total price and the breakdown for the cart of items. Following is the request and response structure
Request:{ "items": [ { "SKU": "ipd", "name": "Super iPad", "price": 549.99, "image": "/images/ipd.jpeg", "quantity": 6 } ] }Response:
{ "total": 2999.94, "breakdown": [ { "SKU": "ipd", "name": "Super iPad", "quantity": 6, "originalPrice": 549.99, "finalPrice": 2999.94, "discountApplied": 300, "discountDescription": "Bulk discount applied for purchasing more than 4" } ] } -
index.js- Contains the homepage of the application available at the route"/". -
checkout.js- Contains the checkout page available at the route"/checkout"that user lands on once they click on checkout from the cart sidebar. Users can only land on this page if their cart has items. -
success.js- Contains the success page available at the route"/success"that user lands on once they confirm their purchase on checkout page. Users can only land on this page if their cart has items. -
_app.js- It is used to initialise the pages and apply global settings, it does contain the code wrap the entire application withCartProviderto maintain context of cart across the pages. -
_document.js- It is for customizing the overall HTML document structure. Currently, it just imports the fontInterbut it can be used for further customisation to HTML document structure for server-side rendering optimizations.
The corresponding tests are available in tests/pages folder.
context contains context files, currently it has CartContext which maintains the state of cart across the application. It makes use of localStorage to preserve the state even on reloads.
hooks contains hooks that can be used on frontend across the application. Currently, it has useFetchPriceDetails hook that fetches the price details of a cart from /api/checkout API.
components contains all the reusable components of the application. Following are the components available -
CartIcon.js- Contains theCartIconcomponent which shows whether the cart of the user is empty or not and opens cart sidebar on clicking.CartProductCard.js- Contains theCartProductCardcomponent which displays a specific item in the cart along with the price and quantity with an option to be removed from the cart.CartSidebar.js- Contains theCartSidebarcomponent which displays the cart sidebar that opens when user clicks on the cart icon. It asks the user to add items to cart if the cart is empty.ProductCard.js- Contains theProductCardcomponent which displays the product with image and it's details. It also contains a CTA to "Add to Cart".ProductList.js- Contains theProductListcomponent which displays the list of products in a responsive grid.
The corresponding tests are available in tests/components folder.
The styles for the application are placed in styles folder. Currently, it contains globals.css defining the globally applied styles.
The folder stucture for the project is as follows -
online-store/
├── public/ -> contains public files
│ ├── images/
│ │ ├── atv.jpg
│ │ ├── ipd.jpg
│ │ ├── mbp.jpg
│ │ ├── vga.jpg
│ ├── favicon.ico
│ ├── next.svg
│ └── vercel.svg
├── src/ -> contains backend and frontend
│ ├── components/
│ │ ├── CartIcon.js
│ │ ├── CartProductCard.js
│ │ ├── CartSidebar.js
│ │ ├── ProductCard.js
│ │ └── ProductList.js
│ ├── context/
│ │ └── CartContext.js
│ ├── hooks/
│ │ └── useFetchPriceDetails.js
│ ├── models/
│ │ ├── pricingRules.js
│ │ └── products.js
│ ├── pages/
│ │ ├── api/
│ │ │ └── checkout.js
│ │ ├── _app.js
│ │ ├── _document.js
│ │ ├── checkout.js
│ │ ├── index.js
│ │ └── success.js
│ ├── styles/
│ │ └── globals.css
│ └── utils/
│ └── calculateTotalPriceAndBreakDown.js
├── tests/ -> contains tests
│ ├── components/
│ │ ├── CartIcon.test.js
│ │ ├── CartProductCard.test.js
│ │ ├── CartSidebar.test.js
│ │ ├── ProductCard.test.js
│ │ └── ProductList.test.js
│ ├── pages/
│ │ ├── api/
│ │ │ └── checkout.test.js
│ │ ├── checkout.test.js
│ │ └── index.test.js
│ └── utils/
│ └── calculateTotalPriceAndBreakDown.test.js
├── .eslintrc.json
├── .gitignore
├── babel.config.js
├── jest.config.js
├── jsconfig.json
├── LICENSE
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── README.md
└── tailwind.config.js
The UI is targetted to be simplistic in nature and easy to navigate, the application has been built to handle dark and light modes from the system settings. Feel free to toggle and check for the same.
To make the user experience more intutitive and effortless, there have been animations added for hover and state changes to the cart. Do check by navigating around.
To update the pricing or the pricing rules, feel free to update models and restart the server locally.
The project has been deployed using vercel and is available at - https://online-store-cs.vercel.app