Or Go to the live site and try it for yourself here
- This is an e-commerce app that allows shoppers to view, sort, and filter products according to different criteria. After products are added to the shopping cart, payment is processed with Stripe API.
- This serves as a TypeScript, Sanity CMS, GraphQL, and Stripe API learning project. I took the skeleton of this Udemy course project. The differences between the original one and my version are:
- replaced the JavaScript code with TypeScript.
- Instead of using dummy data and API provided by the Udemy course, I use some real product data from a friend's Instagram store. Sanity CMS is used to host the data, GraphQL is used to query the data.
- react.js (create-react-app)
- TypeScript
- styled-components
- CSS
- react-router
- Stripe API
- Sanity
- GraphQL
- axios
- Netlify
-
A simple Sanity CMS schema is used: add, amend or delete product can be done on the CMS instead of in the source code.
-
Click on each
ServicesCard
button will do two things:
- route to
ProductsPage
; - filter the products according to which button gets clicked on.
- To achieve this, it has to go through three steps:
- clear the previous filters
- set
isClickFromServices
state variable to tru - update filters according to the button that gets clicked on
Click here for the relevant code.
- Why is there a
isClickFromServices
variable?ProductsPage
should display products of relevant service if routed fromServices
component.- But each time
ProductsPage
is mounted,filters
are cleared since the page should display all products. - That means there are two cases for
ProductsPage
:- when the component mounts
filters
are cleared. - when the component mounts, and it is routed from
Services
component,filters
should contain a value.
- when the component mounts
- Therefore, an if statement is used to check if the page is routed from
Services
, click here for the relevant code.
-
Shoppers can choose to view the products in
ListView
orGridView
. Click here for relevant code. -
Shoppers are able to filter products by different criteria, such as keyword, price, etc.
-
Products can be sorted by price or name, in ascending or descending order Click here for sorting function.
-
Payment is processed by Stripe API, click here for relevant code.
-
Please note that the newsletter subscription part on
HomePage
does not do anything.
Lots of thoughts were given about filter functions related to 'age' and 'height' because of the nature of the baby product. I am listing some reasons why age
and height
filters are set up in this way:
- create "baskets of categories"
- Baby products, in general, are labelled as suitable for different ages, for instance:
- 3-6 months
- under 1 year old, or
- all ages
- To filter the products according to these age descriptions, first I need to create some "baskets" of fixed categories like these:
- 0-3 months
- 3-6 months
- 6-9 months
- 9-12 months
- 12-24 months
- 24 months +
- Then assign a product one or more of these categories. For example,
- if a product is suitable for an infant of
3-6 months
, then assign only such category. - if a product is labelled
0+
, i.e. suitable for all ages, then all of these categories should be assigned to the product.
- if a product is suitable for an infant of
- Why use checkboxes for
age
filter, instead of selection tabs likecategory
?
-
A product can only be either a piece of
toy
or a piece ofclothing
, but cannot be both. Click on the selection tab oftoy
should display all thetoy
products. -
But a product can be suitable for multiple age categories, for example, a product for an infant under 6 months should have both
0-3 months
and3-6 months
. Since multiple choices can be selected at the same time, checkboxes should be used. -
By default when the page mounts, it displays all products, which implicitly means none of the filters are applied. So a checkbox of
all
is not needed forage
(unlikecategory
filter) because the app should allow the user to apply different criteria one by one, instead of applying all the filters for the user by default.
- Other than the 'category baskets', there should be text descriptions about
age
andheight
.
- if a product is suitable for an infant of height 65 cm, it is inside the category of
60-69 cm
for filtering purposes. - But in the
singleProductPage
, it states "suitable for height: 65cm" to provide some readable text to the user. - That means there are two fields related to 'height' factor in the Schema:
height
refers to the categories (e.g. '60-69 cm'), a product can have zero or multiple of such categories.heightDescription
refers to the text description specified from the product manufacturer, which is also a more precise product description in readable text.
- When I started the project, the latest react-router v6 was released.
- I chose to keep using react-router v5 instead since this project is mainly a TypeScript learning project. Adapting to the latest version of react-router wasn't my priority.
-
Filter in mobile view should use a modal instead of a toggle-able menu.
-
Schema design should take into account that that one product can have different variants. For instance, A product with different colours and sizes.
- Different variants of a product should have the same
product_id
, but a differentSKU
. But since this is not a real store that gets used, it is not implemented in this project.
- Different variants of a product should have the same
From your command line, first clone this repo:
# Clone this repository
$ git clone https://github.com/1codingguy/typescript-e-commerce.git
# Go into the repository
$ cd typescript-e-commerce
# Remove current origin repository
$ git remote remove origin
Then you can install the dependencies using NPM:
# Install dependencies
$ npm install
# Start development server
$ npm start
Happy coding!
coding-guy