We at Waves Trendy are dedicated to provide beautiful and new trend fashion dresses, uniting and sustainable products to individuals, love birds and families. With our method to only produce whats demanded by our customers and delivering longlasting, high quality products we want to counter the biggest problems of the western society. Our products are locally produced in America and we only use materials where we know the origin, to guarantee 100% ethical and sustainable products.
This site is the final Milestone Projects that made up the Full Stack Web Development Course at Code Institute. The core requirements focus on bulding a fullstack site with the use of Django, Python, JavaScript, HTML, CSS and a relational database. The final result is hosted on Heroku, while storing static and media files on an S3 Cloudstorage from AWS. The store is connected to Stripe.
To test the site incl. the checkout process please use the test credit card number provided in the Stripe Documentation:
- Number: 4242 4242 4242 4242
- Exp. Date: Anything (e.g. 02/24)
- CVC: Anything (e.g. 242)
- Waves Trendy
- Table of Content
- UXD Considerations
- Information Architecture
- Features
- Technologies Applied
- Testing
- Deployment
- References, Credits & Acknowledgment
- Fair use disclaimer
The aim of this project is to create an ecommerce shop for sustainable clothing and some home equitment. The goal is to create this shop as an interactive fullstack website that allows customers to browse products, make purchases by credit card and if registered manage a wishlist or see their orderhistory. These goals should be supported by providing a clean and easy to use website that allows seamless navigation and has a low bounce rate.
Before laying out the project and creating an initial design market research was done. During this research phase the following questions were also acknowledged:
- How do other stores look?
- What are typical design patterns used across stores?
- Which site are appealing to me?
- Which kind of stores fit to my business idea?
The shop is targeted to women and men alike. The typical age of a shopper is estimated to be between 25 and 40 years. Especially couples and small families are targeted with the products. All customers have mindset respecting the environment and favoring sustainable products. The income of the target group is an average mid to high household income. Furthermore the target group has a passion for living outdoors and owning sustainable high quality products to use in day to day life.
Before the start of the Project the Epics and User Stories were defined and written out to have complete set of necessary features to get the site going. In total 6 Epics were defined and user stories were broken down into 3 user groups:
- regular site visitors
- registered users
- the store manager/owner.
As a site visitor, i want to...
- ... access the website with any device (smartphone, tablet, desktop), so that i am able to visit the shop anytime and anywhere.
- ... have easy navigation, to quickly solve the reason for my visit.
- ... have information about the brand, to get to know the company and understand their mission and story.
- ... be able to contact the company, so that i quickly can get in touch if i have a question or issue.
As a site visitor, i want to...
- ... browse products by category and productline, so that i quickly find what i am looking for.
- ... sort products, to adjust the order according to my needs.
- ... be able to search for specific products, to quickly get what i need.
- ... to access product details, to get more information on an item.
- ... be able to choose a size, to order the necessary items according to my needs.
As a site visitor, i want to...
- ... see all my items in a cart, so that i have an overview of my potential purchase.
- ... be able to reduce / increase quantity, so that i can order my prefered amount.
- ... be able to remove an item from my cart, so that i can manage my cart efficiently.
- ... be able to checkout from the cart view, so that i can quickly finish my purchase.
- ... be able to pay a order by credit card, so that i don't have to deal with an invoice and money transfer.
- ... receive an order confirmation, so that i know my order was received.
As a registered user, i want to...
- ... have my details prefilled from my profile, so that i quickly can finish my purchase
As a site visitor, i want to...
- ... be able to sign up to the store, so that i can track orders and have my data prefilled in the order form.
As a registered user, i want to...
- ... be able to login, so that i can access my useraccount.
- ... be able to see my order history, so that i know what i've purchased in the past.
- ... manage my personal details, so that i can quickly update my data if something changes.
As a registered user, i want to...
- ... add/remove items to my wishlist, so that can save items for later purchase to my useraccount.
- ... have an overview of my wishlist, to get an overview of my already added products.
As a store owner, i want to...
- ... be able to manage the products, categories, productlines and productvariants, so that i have an overview of my inventory.
- ... manage blog entries, to add new/edit posts on the blog to provide customers some additional value.
- ... manage FAQs, so that i can quickly update often asked questions
The wireframes were created in Figma. Figma is a cloud based desing tool which allows you to rapidly create prototypes, wireframes and layouts Figma
The whole figma project can be accessed here: Waves Trendy
The project brief required to base the project on the Django application framework - "The web framework for perfectionists with deadlines". Django is an open source python web framework that takes away the burdens of regular web development and allows developers to quickly build a secure, scalable and state-of-the art app.
During development the built-in SQLite3 database from django is used. However, for the deployment to Heroku a switch to postgressql was undertaken. Django’s authentication system in combination with django-allauth is used to manage users and permissions. The structure of the products and checkout app are based on the Boutique Ado project from Code Institute and customized to the specific project needs.
Name | Type | Example Data |
---|---|---|
name | CharField(max_length=254) | grown_ups |
display_text | CharField(max_length=254) | Grown Ups |
image | ImageField(null=True, blank=True) | |
image_url | URLField(max_length=1024, null=True, blank=True) |
Name | Type | Example Data |
---|---|---|
name | CharField(max_length=50) | tshirt |
display_text | CharField(max_length=254) | T-Shirt |
Name | Type | Example Data |
---|---|---|
category | ForeignKey( 'Category') | 1 |
productline | ForeignKey( 'ProductLine') | 1 |
name | CharField( max_length = 254 ) | passionate |
display_text | CharField( max_length = 254 ) | Passionate Puffin |
price | DecimalField(max_digits=6, decimal_places=2, validators=[MinValueValidator(0.01)], blank=True) | 49.95 |
discount_price | DecimalField(max_digits=6, decimal_places=2, validators=[MinValueValidator(0.01)], blank=True) | 39,96 |
is_on_sale | BooleanField(default=False) | True |
avail_for_pre_order | BooleanField( default = False ) | False |
date_of_dispatch | CharField( max_length = 254 , blank = True , null = True ) | null |
discontinued | BooleanField( default = False ) | false |
image | ImageField( null = True , blank = True ) | passionatepuffin.png |
image_url | URLField( max_length = 1024 , null = True , blank = True ) | |
description | TextField( null = True , blank = True ) | |
is_featured | BooleanField( default = False , null = True , blank = True ) | True |
color | CharField( max_length = 254 , null = True ) | |
material_1 | CharField( max_length = 254 , null = True , blank = True ) | |
material_2 | CharField( max_length = 254 , null = True , blank = True ) | "" |
Name | Type | Example |
---|---|---|
SIZE_CHOICES | [('NO', 'None'), ('XS', 'Extra Small'), ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ('XL', 'Extra Large'),] | |
shirt_size | CharField( max_length = 2 , choices =SIZE_CHOICES) | XS |
Name | Type | Example |
---|---|---|
product | ForeignKey('Product', on_delete=models.CASCADE) | null |
size | ForeignKey('ProductSize', on_delete=models.CASCADE) | XS |
quantity | IntegerField( validators =[MinValueValidator( 0.0 )]) | 9 |
Name | Type |
---|---|
order_number | CharField( max_length = 32 , null = False , editable = False ) |
user_profile | ForeignKey(UserAccount, on_delete =models.SET_NULL,null = True , blank = True ,related_name = 'orders' ) |
order_status | CharField( max_length = 1 , choices =STATUS_OPTIONS, default = '0' ) |
first_name | CharField( max_length = 50 , null = False , blank = False ) |
last_name | CharField( max_length = 50 , null = False , blank = False ) |
EmailField( max_length = 254 , null = False , blank = False ) | |
phone_number | CharField( max_length = 20 , blank = True ) |
country | CountryField( blank_label = 'Country' , null = False , blank = False ) |
zipcode | CharField( max_length = 20 , null = True , blank = False ) |
town_or_city | CharField( max_length = 40 , null = False , blank = False ) |
street_address1 | CharField( max_length = 80 , null = False , blank = False ) |
street_address2 | CharField( max_length = 80 , blank = True ) |
total_order | DecimalField( max_digits = 10 , decimal_places = 2 , null = False , default = 0 ) |
total_tax | DecimalField( max_digits = 10 , decimal_places = 2 , null = False , default = 0 ) |
tax_rate | DecimalField( max_digits = 6 , decimal_places = 2 , null = False , default = 0 ) |
delivery_cost | DecimalField( max_digits = 10 , decimal_places = 2 , null = False , default = 0 ) |
grand_total | DecimalField( max_digits = 10 , decimal_places = 2 , null = False , default = 0 ) |
date_order_placed | DateTimeField( auto_now_add = True ) |
original_cart | TextField( null = False , blank = False , default = '' ) |
stripe_pid | CharField( max_length = 254 , null = False , blank = False , default = '' ) |
Name | Type |
---|---|
order | ForeignKey(Order, null = False , blank = False , on_delete =models.CASCADE, related_name = "lineitems" ) |
productvariant | ForeignKey(ProductVariant, null = False , blank = False , on_delete =models.CASCADE) |
quantity | IntegerField( blank = False , default = 0 ) |
lineitem_total | DecimalField( max_digits = 6 , decimal_places = 2 , null = False , default = 0 , editable = False ) |
Name | Type |
---|---|
user | OneToOneField(User, on_delete =models.CASCADE) |
default_phone_number | CharField( max_length = 20 , null = True , blank = True ) |
default_street_address1 | CharField( max_length = 80 , null = True , blank = True ) |
default_street_address2 | CharField( max_length = 80 , null = True , blank = True ) |
default_zipcode | CharField( max_length = 20 , null = True , blank = True ) |
default_town_or_city | CharField( max_length = 40 , null = True , blank = True ) |
default_country | CountryField( blank_label = 'Country' , null = True , blank = True ) |
Name | Type |
---|---|
user_profile | OneToOneField(UserAccount, on_delete =models.CASCADE, null = False , blank = False) |
wished_products | ManyToManyField(Product, related_name = 'userwishlists' ) |
Name | Type |
---|---|
CATEGORY_CHOICES | [( '1' , 'General' ), ( '2' , 'Return' ), ( '3' , 'Pre Order' ), ( '4' , 'Delivery' ), ( '5' , 'Payment' ),] |
category | CharField( max_length = 1 , choices =CATEGORY_CHOICES) |
name | CharField(max_length = 120 , null = True, blank = False ) |
title | CharField(max_length = 120 , null = True , blank = False ) |
answer | TextField() |
created_at | DateTimeField(auto_now_add = True ,null = False ) |
updated_at | DateTimeField(auto_now = True , null = False) |
Name | Type |
---|---|
author | ForeignKey(UserAccount, on_delete =models.CASCADE, null = False , blank = True ) |
title | CharField(max_length=120, null=True, blank=False) |
subtitle | CharField(max_length=180, null=True, blank=False) |
body | TextField() |
slug | SlugField(unique=True, max_length=250, default=None) |
created_at | DateTimeField(auto_now_add=True, null=False) |
updated_at | DateTimeField(auto_now=True, null=False) |
The following features were thought of. :white_check_mark: - Mark Features that made it into the deployed Project :toolbox: - Mark Features that are interessting for Future Development
- Logged in and non-logged in users see different options ✅
- Searchbar opens below nav when search icon is clicked ✅
- Fixed to top and transparent ✅
- Caroussel with image also behind nav ✅
- Random featured products are chosen to be displayed in caroussel ✅
- Images for featured icons are different from the product picture to be even more appealing 🧰
- Products can be browsed by Category
- Products can be browsed by Category & Productline (e.g.T-Shirt)
- Products can be sorted by...
...Featured Products ...Price ...Color
...Name - Products have different labels based on
Normal Product
Sale Product Pre-Order Productn - Product Details have a Select Option if different sizes are available.
- Product Details have only a "Add to Bag" button if unisize item.
- Partnerlook Section sorts products by name to display matching items side by side.
- Product can be shared on social media 🧰
If registered:
- Product Details allow user to add/remove product to/from wishlist.
- Products a prominently display
- only featured items are rendered
- Bag is present in Side Drawer Container
- Newest Item is always presented on top
- Total inkl. Tax & Shipping
- Checkout straight from Cart Side Drawer
- Add to cart renders updated cart via Ajax-Request
- Increase/Decrease Quantity request via Ajax within Side Drawer Bag 🧰
- Remove Items from Cart ia Ajax-Request within Side Drawer Bag 🧰
- Reserve requested item & quantity to for 10 Min. to avoid checkouts with unavailable products 🧰
If registered:
- attach cart to userprofile instead of saving to session 🧰
- Order summary ✅
- Form to enter shipping address ✅
- Payment via Credit Card ✅
- Users gets order confirmation by mail ✅
- general discount codes can be used 🧰
- personalized discount codes can be used 🧰
- Users receives order updates when order status changes 🧰
If registered:
- Form is prefilled with available user data ✅
- Form data can be saved to userprofile ✅
- Sign up can be undertaken ✅
- Sign up also collected first and last name ✅
- login can be undertaken ✅
- Password reset ✅
- Delete account 🧰
- Sign in with apple or google account 🧰
- User can look up saved address information ✅
- User can update address information ✅
- User can see past orderes ✅
- User can enter detail view of past orders ✅
- User can add/remove items to personal wishlist from product details ✅
- User can view stored wishlist items ✅
- Users can add items to wishlist from product overview 🧰
- users can add items and size to wishlist 🧰
- users can immediatley transform wishlist into order 🧰
- ... can create/read/update/delete products in Django-Admin-View
- ... can create/read/update/delete blogposts in Django-Admin-View
- ... can create/read/update/delete FAQs in Django-Admin-View
- ... can create/read/update/delete Users in Django-Admin-View
- ... Order Management system 🧰
The following technologie were used during the development of the project.
- Sqlite3 (https://www.sqlite.org/index.html)
- postgresSQL (https://www.postgresql.org/)
- CSS (https://www.w3.org/Style/CSS/)
- HTML (https://html.spec.whatwg.org/multipage/)
- Javascript (https://developer.mozilla.org/en- US/docs/Web/JavaScript)
- Python (https://www.python.org/)
- Bootstrap (https://www.bootstrapcdn.com/)
- Django (https://www.djangoproject.com/)
- jQuery (https://jquery.com/)
- Google Fonts (https://fonts.google.com/)
- Gitpod (https://www.gitpod.io/)
- Figma (https://www.figma.com/)
- Boto3 (https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)
- Coverage (https://coverage.readthedocs.io/en/v4.5.x/)
- Dj-Database-URL (https://pypi.org/project/dj-database-url/)
- Django-Countries (https://pypi.org/project/django-countries/)
- Django-Heroku (https://pypi.org/project/django-heroku/)
- Django-Storages (https://django-storages.readthedocs.io/en/latest/)
- Git (https://git-scm.com/)
- GitHub (https://github.com/)
- Gunicorn (https://pypi.org/project/gunicorn/)
- Jigsaw – CSS Validation (https://jigsaw.w3.org/css-validator/)
- JS Hint (https://jshint.com/)
- PEP8 (http://pep8online.com/)
- Pillow (https://pillow.readthedocs.io/en/stable/)
- PIP (https://pip.pypa.io/en/stable/installing/)
- Psycopg2 (https://pypi.org/project/psycopg2/)
- Stripe (https://stripe.com/gb)
- W3C – HTML Validation (https://validator.w3.org/)
- MarkdownTOC (http://ecotrust-canada.github.io/markdown-toc/')
- Heroku (https://www.heroku.com/)
- AWS S3 Bucket (https://aws.amazon.com/)
A detailed description about the testing process and results can be found in the TESTING.md To give a brief overlook of the feature testing this table gives a codensed overview of the tested, features, devices, browsers and results:
Test Case | iPhone Safari | iPhone Chrome | iPhone Edge | iPad Safari | iPad Edge | iPad Brave | Mac Edge | Mac Safari | Mac Chrome |
---|---|---|---|---|---|---|---|---|---|
Test Navbar | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Landing Page | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Shop | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Highlights | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Cart | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Checkout | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Sign Up | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Registered Users: Useraccount | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Registered Users: Wishlist | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
This site is deployed to heroku and the versioning was done with gitpod and the Repository is hosted on Github.
This project can be used for development with the following tools:
- IDE of Choie (i prefer Gitpod)
- Python3, PIP & Git should be installed
Furthermore accounts with the following services are used in this project:
- Stripe
- AWS S3 Storage
- Gmail
Official Github Documentation on cloning a repositiory: [Github - Cloning Repos]
- Navigate to Mainpage of the repository
- Click on "Code" button
- Choose "Clone with HTTPs" & copy URL
- Open Terminal
- Change the current working directory to prefered location
- Type git clone and past copied URL
git clone https://github.com/salute03/waves_trendy_s1
- Press Enter to create local Clone - Make sure your environment supports python3 -
- Type
pip3 install -r requirements.txt
into Terminal - Setup the environment variables. This process is differnet depending on the used IDE. Gitpod supports global Environments for the development process. Therefore they were stored in the settings. The following variables are needed:
DEVELOPMENT=True STRIPE_PUBLIC_KEY = <YOUR STRIPE_PUBLIC_KEY> STRIPE_SECRET_KEY = <YOUR STRIPE_SECRET_KEY> STRIPE_WH_SECRET = <YOUR STRIPE_WH_SECRET>
- Migrate the models and create the database by typing the following commands into the terminal:
python3 manage.py makemigrations
python3 manage.py migrate
- Import the provided fixtures in the following order (copy&paste if you like):
python3 manage.py loaddata categories
python3 manage.py loaddata productline
python3 manage.py loaddata products
python3 manage.py loaddata proudctsize
python3 manage.py loaddata productvariants
python3 manage.py loaddata blog
python3 manage.py loaddata faq
- Create a superuser for accessing the django admin view with the following command:
python3 manage.py createsuperuser
You will be asked for an email address, username and password. - You should be all set and when using the command
python3 manage.py runserver
the project should run. - You can access the django admin view by adding
~/admin
to the end of your (local) URL.
This project is deployed to Heroku. For the deployment the following steps were/are necessary:
- Create/Log in to your Heroku account and create a new App.
- Install Heroku Add-on Heroku Postgres from the Resources tab. The free
Hobby Dev
version is fine. Now click the Provision button to add it to your project. - Create requirements.txt from your project with the help of
pip3 freeze > requirements.txt
(already provided within the repository) - Create a Procfile
echo web: gunicorn puffins.wsgi:application > Procfile
(already provided within the repository) - Commit changes to Git
git add .
followed bygit commit -m "Deploy: Updated Procfile"
(already provided within the repository) - Set the environment variables in Heroku Settings > Reveal Config Variables
The following Variables must be set:
USE_AWS = TRUE AWS_ACCESS_KEY_ID = <YOUR AWS_ACCESS_KEY_ID> AWS_SECRET_ACCESS_KEY = <YOUR AWS_SECRET_ACCESS_KEY> DATABASE_URL = <YOUR DATABASE_URL> (Set by Heroku Postgres) EMAIL_HOST_USER = <YOUR EMAIL_HOST_USER> EMAIL_HOST_PASSWORD = <YOUR EMAIL_HOST_PASSWORD> DEFAULT_FROM_EMAIL = <YOUR DEFAULT_FROM_EMAIL> STRIPE_PUBLIC_KEY = <YOUR STRIPE_PUBLIC_KEY> STRIPE_SECRET_KEY = <YOUR STRIPE_SECRET_KEY> STRIPE_WH_SECRET = <YOUR STRIPE_WH_SECRET>
- Extract the DATABASE_URL Value from the Heroku Settings and set it up in your IDE or local .env file. Make sure to keep this DATABASE_URL a secret and definitly don't commit it to Github.
- To test if the Postgres database is connected to your IDE you can make use of the command
python3 manage.py showmigrations
. This should show undone migrations for all models. - Now migrate the models and create the postgres database on heroku by typing the following commands into the terminal:
python3 manage.py makemigrations
python3 manage.py migrate
- To setup the data in the database import the provided fixtures in the following order (copy&paste if you like):
python3 manage.py loaddata categories
python3 manage.py loaddata productline
python3 manage.py loaddata products
python3 manage.py loaddata proudctsize
python3 manage.py loaddata productvariants
- Create a superuser for the Postgres database for accessing the django admin view with the following command:
python3 manage.py createsuperuser
You will be asked for an email address, username and password. - Log in to heroku from your terminal
heroku login -i
- Add exisitng repository to Heroku heroku
git:remote -a <your repository>
- Push changes to Heroku
git push heroku main
- Visit the app url from heroku and check out your great site!
Code Institute
Category Images:
- Code Institute Boutique Ado-Poject]
Special Thanks to...
- ... my Code-Institute Mentor
- ... Tutors and Fellow Students of slack
- The codes in this project are from the Code Institute Boutique Ado-Poject lessons and was extended and modified to personal needs.
This is for educational use