For the best experience, using a Linux distro or MacOS is recommended. Please also make sure, that make
is installed on your system, as container interaction is abstracted away by Makefile
.
Make comes preinstalled on most distros and MacOS and you can verify its existence by executing
make -v
If its not present you can install it using your OS-specific package manager, for example
[apt / brew / yum / ...] install make
- The app is fully responsive.
- The user is presented a shop page with an option to select a product and amount which he can add to his shopping cart.
- Each product has a maximum amount that can be purchased, which can not be exceeded.
- A maximum of 10 products can be added to the cart.
- The user can see at all times the total price of the cart and the amount of products inside the cart.
- The products display their net and gross price.
- After Checkout the user is presented a success popup.
- The user can navigate to his shopping cart, review and change their order and continue to checkout into limbo.
I organized this project using a Trello board in a Scrumban style. I have made the board public: Trello Orga Board for you to check out.
For the proper experience, and to easily link each task number to the respective feature branch in the commit history, using one of these chrome extensions is highly useful
- Trello Card Numbers
- Trello Card Numbers Plus (This is the one I use, but I can understand suspicion due to the low amount of users.)
Using these extensions one gets the respective ticket number in the card and can then relate them to the feature branches.
This project uses NextJS, and subsequently React, as its primary framework. Although the most current version of NextJs recommends the new App Router as it's now stable, this project will use the traditional Pages/ Routing, as the App Router has mostly not been adopted yet and this project being time-limited.
I thought about using Redux to manage shopping cart state globally, but I decided that for this rather small project, a Context would suffice.
Dependency | Reasoning |
---|---|
MUI Autocomplete | Arguably the best Combobox available. Not only are MUI Components consistent and visually pleasing, they put an emphasis on accessibility, too. Also, don't reinvent the wheel! |
MUI Slider | One of the best free Slider components available. It also integrates well visually with other MUI Components (Autocomplete). Also, don't reinvent the wheel! |
React Toastify | A very capable notification library that is easy to use and set up, reinventing the wheel, especially for notifications, would be a huge time eater. |
Jest | Arguably the most prominent testing library for frontend unit tests in the JS/TS environment. |
@testing-library | Jest without it would not be the same! |
This project uses Makefile to abstract away some of the docker-compose
commands:
Command | Effect |
---|---|
make build | Build the container |
make up | Start the container |
make cli | Enter container CLI (Since 22.06.23 does not create a new container for shell) |
make down | Stop container |
make log | Open the container logs |
make logl | Open the container logs and follow them live |
At the moment, this project utilizes SSG, as the data is statically available and can be fetched serverside from the server-local file system.
The app now uses SSR on the Shop (index) page and fetches the data from an internal API route that provides it with the product data.
As is common, jest
is used in conjunction with @testing-library
to create unit tests for components. I added a handful of unit tests of varying dimension and intricacy, as well as one integration test between the shop order component and the shopping cart.
To run these tests:
npm run test
Or for running the test with the verbose
flag:
npm run vtest
Or for running test and displaying the test coverage:
npm run coverage
For this challenge, getting 100% coverage was not the goal, and would be needlessly time consuming for the scope of the project.
This project leverages two methods of aiding in homogenous and predictable code quality
Tool | Advantage |
---|---|
ESLint | Linting according to specific rules to enforce homogenous development between team members |
Prettier | Code formatting rules to enforce homogenous code appearance between team members |
This project is (almost) ready-to-deploy. The docker setup was configured to use the NODE_ENV
environment variable to determine which mode to start in. Currently there are two modes available: development
and production
, which can be controlled through a .env
file. Please make sure you copy the .env.dist
file, rename it to .env
and assign either development
or production
to the NODE_ENV
variable.
You can see the current environment mode printed first in the container logs (make log
/ make logl
).
Please also make sure to assign the HOST
variable the current app host, otherwise the data fetch will fail.
Given Next is a little finicky with the starting port, the port numbers might have to be adjusted manually in the Dockerfile
, docker-compose.yml
(to be found in docker/
) and package.json
, if your deployment provider requires using certain ports.
From there on, handling the container is identical between dev and prod. Refer to Container Interaction to see which commands are available.
In order to deploy to production:
- Make sure that a .env file exists in the project root
- Set the
NODE_ENV
variable toproduction
and assign theHOST
variable the appropriate host. - (optionally) adjust the port in the
Dockerfile
,docker-compose.yml
andpackage.json
- Build the container using
make build
(optionally tag it) - Push the container image to your preferred Registry
- Pull the image in your cloud provider and integrate it into a project
Of course there were some pitfalls implemented into the requirement. One of them being duplicate product names. Since product names can be identical between different products, the product id was used to differentiate between products, as identical names are a 'to be expected' edge case.
Additionally, the taxRate provided should be used to calculate the gross amount. When looking at BIKE24 web shop, we see that for private customers, the tax is included in the unit price. However, in this scenario, the tax has to be added to the unit price and therefore increases the total gross price, as opposed to being included.
I want to use this dedicated little section to once explicitly mention, that I am not a designer, which probably reflects in the visual appearance of my web shop. However, I do like to translate designs to proper frontends (duh).
The cart is serialized, persisted in localstorage and will be deserialized on page load.
For the short time limit this project entailed, decent responsivity in the design is given.