Skip to content

Commit

Permalink
Initial commit of awesomeness
Browse files Browse the repository at this point in the history
  • Loading branch information
kerkkoh committed Dec 23, 2019
1 parent 209ac9f commit a8d4833
Show file tree
Hide file tree
Showing 37 changed files with 19,210 additions and 1 deletion.
151 changes: 150 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,150 @@
simple-clothing-store
# Simple Clothing Store

![banner](https://i.imgur.com/fg8F52a.png)

[![license](https://img.shields.io/github/license/kerkkoh/simple-clothing-store.svg)](LICENSE)

This project is a simple **clothing store** implemented with **React** and **Node.js**, aiming for an *almost* databaseless design by utilizing a **Printful** integration.

## Table of Contents

- [Demo](#demo)
- [Background](#background)
- [Install](#install)
- [Usage](#usage)
- [Contributing](#contributing)
- [License](#license)

## Demo

The demo has a few limitations for quite obvious reasons.
1. You can't create new orders, some orders are included for you already to view
2. You can't pay for your orders
3. You can't buy anything, or receive products

### > Available on [Glitch](https://simple-clothing-store.glitch.me)

## Background


### Utilized technologies
* APIs
* [Printful REST API](https://www.printful.com/docs)
* [Paypal REST API](https://developer.paypal.com/docs/api/overview/)
* Backend
* [Node.js](https://nodejs.org/en/)
* [Express](https://www.npmjs.com/package/express)
* [currency.js](https://www.npmjs.com/package/currency.js)
* [@paypal/checkout-server-sdk](https://www.npmjs.com/package/@paypal/checkout-server-sdk)
* PrintfulClient utility class (No longer available through Printful)
* Frontend
* [React (with hooks, no classes)](https://reactjs.org/docs/hooks-intro.html)
* [React router](https://www.npmjs.com/package/react-router)
* [Bootstrap](https://getbootstrap.com/)
* [SASS](https://sass-lang.com/)
* [Moment](https://www.npmjs.com/package/moment)
* [currency.js](https://www.npmjs.com/package/currency.js)
* [react-paypal-button-v2](https://www.npmjs.com/package/react-paypal-button-v2)
* [react-helmet](https://www.npmjs.com/package/react-helmet)

### What's working
* Most frontend features:
* Routes implemented with **React router**, including seamlessly moving between pages
* A responsive design implemented with **Bootstrap** and customized with **SASS** (SCSS)
* Loading of products and store data from the server
* Products with multiple images (If printful ever decides to give us a feature for that) and sizes (product variants)
* Persistent shopping cart
* Correct handling of currency as its own datatype via **currency.js**
* Discount codes that are confirmed by the server, and correctly applying them to the cart total
* Showing orders, their statuses & shipping information from **Printful**
* Some backend features:
* Loading products directly from the Printful API
* A configuration file for setting file descriptions, discounts and VAT rates your store needs (This will be changed to be something less hardcoded in the future)

### What's planned/missing
* Frontend:
* Admin panel with minimal controls for
1. Setting product descriptions
2. Creating discounts
3. Monitoring orders
4. Setting the VAT rate
* Handling error cases and displaying messages
* Cancelling of orders
* Quantity for products in a basket
* Backend:
* Hiding information better (product information like printfiles & costs shouldn't be sent to the client)
* Calculating shipping & VAT before confirming the order
* Refactoring
* Better handling of errors
* Handling of missing products, faulty carts, etc.
* Emails

### Why?

This project is a hobby project that I started sketching out back in 2017 and decided to go through with in 2019 after giving it some thought. For me, this was a learning opportunity to familiarize myself with new APIs and solving problems that one might face in an implementation of an ecommerce system with modern web technologies.

Another reason was the lack of **open source** webstores implemented with a JS stack, similar to this project's stack. There are a few out there, but none of them are geared towards a clothing store that operates with Printful. One of this project's goals was also to be as **simple** as possible. This means keeping the stack very light with a focus on JS and popular libraries. This also means that payments are outsourced, production is outsourced, and orders are mostly outsourced. This should keep the maintenance of the system at minimum, while allowing the clothing store to operate smoothly.

### Why should I use it?

In most cases, you shouldn't. Not yet. It is at an early stage of development with most of the features being at most stubs of the eventual or necessary features.

These are some problem areas as of now:
* Lack of a solid user, order or payment database
* Lack of good information hiding from the users of the API
* Security: while I've kept security in mind while developing the system, it hasn't been penetration tested by professionals, and this poses a constant risk if used in productions
* No input validitation/verification of any kind
* No handling situations where the local cart is out of sync with the products in the store

## Install

First, clone the repository from github.


Now you're going to need to setup some configuration files and environmental variables:
1. Get your PayPal & Printful API keys
2. Navigate to `simple-clothing-store/backend/`, and rename the file called `.env.template` to just `.env`
3. Set the variables in the `.env` file without inserting any spaces anywhere in the file. The variable names and comments should explain where to put what adequately. Save the file.
4. Navigate to `simple-clothing-store/frontend/src/` and open the file `config.js`
5. In this file you should specify some information that is displayed on the site. You should also include the same PayPal API client id in this file as a string.
6. Navigate to `simple-clothing-store/backend/lib/` and open the file `datab.js`
7. In this file you can specify
1. Product descriptions in the `items` array by specifying a product id (You can get the id by visiting the store frontend and going to the page of a product, and then viewing the url like `yoursite.com/product/5632658632` where `5632658632` would be the id) and then specifying a `description` string for it.
2. Discount codes in the section `discounts`
3. Your VAT (Value Added Tax) percent **as an integer**.

Now you need to build the frontend and move the built folder into the backend and install everything.
```
cd simple-clothing-store/frontend
npm install && npm build
```
Depending on the operating system, the command for moving the build folder varies, on Linux:
```
mv build ../backend
```
and on Windows:
```
mv build ../backend
```
And then to install the backend:
```
cd ../backend
npm install
```


## Usage

To run the server, make sure you're in the `simple-clothing-store/backend` folder, and run:
```
npm start
```
This will start the server, and host the production build frontend with the port `process.env.PORT` or 3001. You can set the PORT variable in the file `simple-clothing-store/backend/.env` by creating a new line with the port you want the system to run on. If you're using services like Heroku to host the system, they should set this variable for you.

## Contributing

PRs accepted.

## License

[MIT License](https://github.com/kerkkoh/simple-clothing-store/LICENSE.md)
8 changes: 8 additions & 0 deletions backend/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Environment Config
# DO NOT INCLUDE ANY SPACES BETWEEN THE = SIGNS OR ANYWHERE ELSE

# Your Printful API secret should go here
PRINTFUL_SECRET=
# Your PayPal client id and secret should go here
PAYPAL_CLIENT_ID=
PAYPAL_CLIENT_SECRET=
25 changes: 25 additions & 0 deletions backend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
'env': {
'commonjs': true,
'es6': true,
'node': true,
},
'extends': [
'google',
],
'globals': {
'Atomics': 'readonly',
'SharedArrayBuffer': 'readonly',
},
'parserOptions': {
'ecmaVersion': 2018,
},
'rules': {
'indent': ['error', 2],
'linebreak-style': ['error','unix'],
'quotes': ['error','single'],
'semi': ['error','never'],
'no-trailing-spaces': 'error',
'max-len': ['error', {'code': 120 }]
},
};
4 changes: 4 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
.env
build
examples.js
19 changes: 19 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Simple Clothing Store


Hey ya! ╰( ̄ω ̄o)


I am the backend that hosts the built for production frontend, and also acts as an api middleground to allow communication between the frontend and the various APIs we're using! I'm mostly made out of Node.js & Express.


## I'm using
* A few very nice APIs
* [Printful REST API](https://www.printful.com/docs)
* [Paypal REST API](https://developer.paypal.com/docs/api/overview/)
* Some awesome libraries
* [Node.js](https://nodejs.org/en/)
* [Express](https://www.npmjs.com/package/express)
* [currency.js](https://www.npmjs.com/package/currency.js)
* [@paypal/checkout-server-sdk](https://www.npmjs.com/package/@paypal/checkout-server-sdk)
* PrintfulClient utility class (No longer available through Printful)
30 changes: 30 additions & 0 deletions backend/lib/datab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable max-len */
/**
* Temporary Database/Configuration file
*
* For the "items" array, you get the id from the page of the product, or via the printful API.
* If you don't set a description, the system will automatically tell you what sort of object
* you should enter here for the description to work.
*
* In the discounts object, you have key-value pairs where the key is the string discount,
* and the following integer is 100-yourDiscount --> A 20% discount should be 100-20 = 80
*
* The "vat" entry is simply the percentage amount that your customers need to pay in VAT/
* value added tax.
*/
// TODO: should be changed to lowdb/nedb/mongodb in the future
// Todo: Make the discount amount more logical
const db = {
items: [
{
'id': 5632658632,
'description': 'This description would appear at yoursite.com/product/5632658632 if there was a product with this id.',
},
],
discounts: {
'TEST': 80,
},
vat: 24,
}

module.exports = db
59 changes: 59 additions & 0 deletions backend/lib/paypal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* eslint-disable valid-jsdoc */
/* eslint-disable require-jsdoc */
'use strict'

/**
*
* PayPal Node JS SDK dependency
*/
const checkoutNodeJssdk = require('@paypal/checkout-server-sdk')

/**
*
* Returns PayPal HTTP client instance with environment that has access
* credentials context. Use this instance to invoke PayPal APIs, provided the
* credentials have access.
*/
function client() {
return new checkoutNodeJssdk.core.PayPalHttpClient(environment())
}

/**
*
* Set up and return PayPal JavaScript SDK environment with PayPal access credentials.
* This sample uses SandboxEnvironment. In production, use LiveEnvironment.
*
*/
function environment() {
const clientId = process.env.PAYPAL_CLIENT_ID
const clientSecret = process.env.PAYPAL_CLIENT_SECRET

return new checkoutNodeJssdk.core.SandboxEnvironment(
clientId, clientSecret,
)
}

async function prettyPrint(jsonData, pre='') {
let pretty = ''
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase()
}
for (const key in jsonData) {
if (jsonData.hasOwnProperty(key)) {
if (isNaN(key)) {
pretty += pre + capitalize(key) + ': '
} else {
pretty += pre + (parseInt(key) + 1) + ': '
}
if (typeof jsonData[key] === 'object') {
pretty += '\n'
pretty += await prettyPrint(jsonData[key], pre + ' ')
} else {
pretty += jsonData[key] + '\n'
}
}
}
return pretty
}

module.exports = {client: client, prettyPrint: prettyPrint}
Loading

0 comments on commit a8d4833

Please sign in to comment.