Surf Matters
About
Surf Matters is an e-commerce store, specialising in Surf Boards and Wetsuits and Surf Lessons. The site was built with a friend in mind to showcase what an e-commerce store would look like for them as they are looking to open a surf shop shortly.
Users are able to browse the products, sort by various categories and filter categories into certain products and subcategory of products. A product details page enable users to view further information on individual products and add them to their shopping bag to purchase.
There is also a blog page where users can browse submitted articles and leave comments, users are encouraged to submit articles themselves via email.
Users are able to register for a new account, and once registered they can login and view their default delivery information and previous order history.
The deployed website can be viewed here -Surf Matters
UX
The website was designed to be responsive and easy to use and navigate. I designed a home page with an image carousel of various surfing images, with button links to the products, surf lessons and blog.
The site is easy to navigate, users can use the menu links in the navigation bar at the top of the page, and each page has a consistent layout to it with the header and footer replicated across the site, this gives users a familiar feel to each page when navigating the site.
I chose black and white as the main colours for the site as the surfing, product and blog images are quite colourful due to the nature of their content.
Site Goals
The overall aim of the site is to enable users to access the online store for the Surf Matters surf shop. It is designed to be somewhere that Surf Matters can showcase their products online and also sell other services they offer to a far wider audience than just the people who visit their shop.
The inclusion of a blog is designed to give the store a community feel, users are encouraged to email in an article for the site owner to approve before posting.
Target Audience
The website is aimed at but not restricted to the following users :
- People wanting to buy surf products.
- People wanting to learn to surf.
- Site owner to increase sales and manage products.
- People wanting to find surf shops local to them.
User Stories
User Story ID | As A/AN | I want to be able to... | So that I can.. |
---|---|---|---|
Viewing and navigation | |||
1 | Shopper | View all products. | Select what I would like to purchase. |
2 | Shopper | View individual product details. | See the price, product description and any other information about the product. |
3 | Shopper | Add items to a shopping bag. | Review what I want to purchase. |
4 | Shopper | View the total of my purchases. | Avoid over spending. |
Registration and User Accounts | |||
5 | Site User | Register for an account. | Have a profile with saved details such as delivery address and previous orders. |
6 | Site User | Login and logout. | Access my personal information. |
7 | Site user | Receive email comfirmation after registering. | Check that my account registration was a success. |
8 | Site User | Recover my password if I forget it. | Maintain access to my account. |
Purchasing and checkout | |||
9 | Shopper | Select the size and quantity of a product. | Make sure I purchase the correct product for me. |
10 | Shopper | View items in my bag before purchase. | Check the cost and items that I want to buy. |
11 | Shopper | Amend or delete items in my bag. | Make changes if I change my mind about certain purchases. |
12 | Shopper | Securely make a payment. | Be confident my personal details are not shared with anyone. |
Sorting and searching | |||
13 | Shopper | Sort the list of products. | Find the best price or best rated product. |
14 | Shopper | View products by category. | View specific products that I am in interested in. |
15 | Shopper | Search for a product by name. | Find a specific product I am interested in. |
Admin and Product Management | |||
16 | Site / Store Owner | Add a product. | Increase the product range I am selling. |
17 | Site / Store Owner | Edit a product. | Change product prices, descriptions etc. |
18 | Site / Store Owner | Delete a product. | Remove products that are no longer available. |
Blogs | |||
19 | Site User | Read blog articles. | Read about a subject of interest to me. |
20 | Site User | Comment on a blog article. | Let the author know how I felt about their post. |
Database Schema
The databases are stored in sqlite3 in development, and heroku postgres in production. A number of different models are used throughout the site as detailed in the database schema below.
Product model
The product model holds all the information relating to products sold in the store, it has two foreign keys, those being category and subcategory, and is also a foreign key to the OrderLineItem model.
Field | Type |
---|---|
category | models.ForeignKey |
subcategory | models.ForeignKey |
sku | models.Charfield |
name | models.Charfield |
description | models.TextField |
has_sizes | models.BooleanField |
price | models.DecimalField |
rating | models.DecimalField |
image | models.ImageField |
Category and Subcategory models
The Category and Subcategory models are identical, both contain two fields. A name field which is used in the back end. The other field is a friendly_name which is used to display the name to the end user.
Field | Type |
---|---|
name | models.Charfield |
friendly_name | models.Charfield |
Order model
The order model is created in the checkout app, and is used to handle all orders across the site. It takes the user_profile as a Foreign key to bring across registered users stored details.
Field | Type |
---|---|
order_number | models.CharField |
user_profile | models.ForeignKey |
full_name | models.CharField |
models.EmailField | |
phone_number | models.CharField |
street_address_1 | models.CharField |
street_address_2 | models.CharField |
town_or_city | models.CharField |
county | models.CharField |
post_code | models.CharField |
country | models.CountryField |
date | models.DateTimeField |
delivery_cost | models.DecimalField |
order_total | models.DecimalField |
grand_total | models.DecimalField |
original_bag | models.TextField |
stripe_pid | models.CharField |
OrderLineItem model
The order line item model is used to create an order line for each product in the shopping bag. It takes in the order as a Foreign Key, which enable us to access orders and make certain calls on them. It also takes in product as a Foreign Key, which gives it access to all the associated fields of that model.
Field | Type |
---|---|
order | models.ForeignKey |
product | models.ForeignKey |
product_size | models.CharField |
quantity | models.IntegerField |
lineitem_total | models.DecimalField |
UserProfile model
The UserProfile model is used to store a customers default delivery information, and also to provide a record of their order history. It has user as a OneToOneField which specifies that each user can only have one profile, and each profile can be attached to one user.
Field | Type |
---|---|
user | models.OneToOneField |
default_phone_number | models.CharField |
default_street_address_1 | models.CharField |
default_street_address_2 | models.CharField |
default_town_or_city | models.CharField |
default_county | models.CharField |
default_country | models.CountryField |
default_postcode | models.CharField |
Blog model
The blog model holds all the data for the individual blogs. The slug field is used to create a URL for each individual blog item.
Field | Type |
---|---|
title | models.Charfield |
slug | models.SlugField |
opening | models.TextField |
body | models.TextField |
date | models.DateTimeField |
image | models.ImageField |
author | models.Charfield |
Comment model
The comment model is used to add comments to the blog articles.
Field | Type |
---|---|
post | models.ForeignKey |
name | models.Charfield |
models.EmailField | |
comment | models.TextField |
date | models.DateTimeField |
active | models.BooleanField |
Wireframes
Home Page
Registration Page
Login Page
Products Page
Individual Product Page
Surf Lessons Page
Individual Surf Lessons Page
Blog Page
Checkout Page
Shopping Bag Page
Profile Page
Features
-
Navigation Bar - The site features a consistent navigation bar, it uses Bootstrap responsive navbar, it is easy to use and collapses down on smaller devices.
-
Search Box - The navigation bar has a search box, where users can enter search terms to search for relevant products in the store.
-
Product Sorting - Users have the ability to sort products by name, price and rating.
-
Product Filtering - Users can filter products by category and subcategory.
-
Shopping bag - Users are able to add products to their shopping bag whilst browsing the store. When viewing the bag they can update (i.e. change sizes), or remove products they no longer wish to purchase.
-
Toast Messages - The site features Bootstrap toast messages. Users get success messages when performing operations such as logging in and out and adding products to their bag. Users also reveive error, info and warning messsages.
-
Account Registration - Users are able to enter their details and register for an account.
-
Profile Page - Users get a profile page, which stores their default delivery information and previous order history.
-
Secure Checkout - Users can checkout and purchase goods securely, the site utilises Stripe, a secure online payment processing facility.
-
Blog Comments - Users are able to add their comments to the blog articles, using a form at the bottom of each blog article. The comments are then displayed underneath the article.
Technologies Used
HTML5 - Used to provide the structure and content of the templates.
CSS - Provides some of the styling for the site.
Bootstrap - Utilised for a lot of the styling of the site such as product card and forms. Also used to make the site responsive. Bootstrap 4.6 was chosen as Crispy Forms are not available with Bootstrap 5.
Python - The main code used in the back end with Django.
Django - A Python web framework used to create the website.
Django allauth - Used for account authentication, registration and account management.
Django crispy forms - Used for styling the websites forms, to make them match the Bootstrap theme.
Django template engine - Used as a templating language with Django and Python.
Stripe - A secure online payment processing facility, used for processing customer payments.
Sqlite3 - Used for storing the databases when in develoment.
Heroku Postgres - Used for storing the databases in production.
jQuery - Used for functionality of the site such as the Bootstrap carousel and stripe elements.
Google Fonts - The site uses the Oswald and Roboto fonts.
Font Awesome - Used for the icons throughout the app.
Git - Used for version control, and tracking changes in the repository.
Heroku - The platform used to deploy the app.
Testing
A lot of the testing was carried out in develoment, using the developer tools in Google Chrome. I found this the most productive way of testing as I found that I could fix issues found as I went along. The developer tools also assisted me in testing the responsiveness of the site.
User Story Tests
I have created a separate file for the user story tests, you can find them by clicking here.
The website was tested using a Microsoft Surface Pro on Windows 10, on the following browsers.
- Google Chrome - Version 88.0.4324.182 (Official Build) (64-bit)
- Microsoft Edge - Version 88.0.705.74 (Official build) (64-bit)
- Mozilla Firefox - 85.0.2 (64-bit)
The site functioned well in all of these browsers. Stripe payments worked correctly. All forms displayed and functioned in the right way. Images were displayed as they should be, and all items were rendered correctly.
The app was also tested on a number of devices as listed below.
-
Google Pixel 3 xl using Google Chrome on Android 11.
-
Moto E5 using using Google Chrome on Android 8.1.
-
Ipad 6th Generation using Safari on IOS 13.4.
-
Iphone 11 using Chrome on IOS 14.4.
I used the following websites for validation of my code
Issues found in testing
-
The Surf Lessons were displaying on the all products page, when they should only be displayed on the Surf Lessons page. To resolve this I created a category objects filter for the surf lessons in the all_products view. Then created a products filter to not include the surf lessons.
-
No products were displaying after adding the product filter in the all_products view. This was resolved by changing the products.filter to category__name__exact instead of category__name__in.
-
On the checkout page the processing overlay was appearing on mobile devices after pressing the navbar hamburger link. I realised that I hadn't given an ID to the checkout button so the overlay was looking for any element with a class of button. This worked correctly once this was changed.
-
After logging in with your username and password, a toast message should appear saying succesfully logged in. This was not showing on the site, however when inspecting in Dev tools the HTML elements for the toast message were there. I found that the Bootstrap Jquery for the toast message was not working fully on the home page. So I copied across the Jquery code to the postloadjs on the home page.
-
The comments form on the blog details page was not responsive, causing the user to side scroll. I resolved this by rendering it as a crispy form.
Deployment
Surf Matters was developed using Gitpod as an IDE, Github is used to store the repository and for version control. The website is deployed on Heroku.
The following steps are taken to deploy the website.
- Navigate to my Surf Matters Github repository - https://github.com/adamparker75/Surf_Matters
- Click on the dropdown that says code.
- A URL is displayed, to clone with HTTPS copy this URL
- Open up your preferred IDE (Integrated Development Environment)
- Change the directory to the location you want the clone to be made.
- Type git clone and then paste the copied URL from step 3.
- Press Enter and your local clone will be created.
- In your Environment variables ensure you add the following.
-
You may have to create a Stripe account to obtain the public and secret keys.
-
Install the requirements.txt file by typing the following command.
pip3 install -r requirements.txt -
Carry out a migrate with the following command.
python3 manage.py migrate
Deploying to Heroku
- In your IDE create a Procfile and add the following on the top line.
web: gunicorn surf_matters.wsgi:application - Commit and push the files to Github.
- Navigate to Heroku and login. https://id.heroku.com/login
- Click on the new button and then choose create new app.
- Give your app a name, select a region and then click create app.
- In the deploy tab of your app, click connect to Github.
- Search for your repository name, once found click connect.
- Click the settings tab and then click reveal config vars.
- Add in the following config variables. The same as in your environment variables. The email variables are taken from Gmail.
- Click back to the deploy tab, choose a branch to deploy and then click enable automatic deploys.
- In the resources tab search for Postgres in add-ons
- Choose hobby/dev then click submit order form.
- Click open app at the top of the page.
The site is now deployed on Heroku.
Amazon Web Services (AWS)
I have hosted the static files and media files for the deployed site in an Amazon Web Services S3 bucket. To store the files an S3 bucket needs to be created, the documentation for setting one up can be found here. You will need to use the below code for your CORS configuration when required.
Once the set up is complete you will be given a CSV file titled new_user_credentials. Download this file as it holds the Access_key_ID and the Secret_Access_key which are needed to add to your Heroku config vars and, development environment variables.
Back in your IDE follow the below steps.
-
Run the following commands.
pip3 install boto3
pip3 install django-storages -
Freeze to requirements.txt
pip3 freeze > requirements.txt -
In settings.py add storages to **INSTALLED_APPS
- If not already there the following will need to be added to settings.py
- In the project root directory create a custom_storages.py file and add the following code.
- Commit the changes and push to Github and Heroku.
Credits
Content
- The code for the navigation bar was taken from Bootstrap.
- The code for the account and bag links was taken from The Code Institute Boutique Ado project.
- The footer was taken from MD Bootstrap.
- The Bootstrap carousel was taken from Codepen.
- The blog templates were taken from Start Bootstrap.
- The blog comments form was created with help from Django Central.
- Overlay and spinner taken from JS Fiddle.
- Product searching, filtering and sorting was created with help from The Code Institute Boutique Ado project.
- The wireframes were created with Balsamiq.
- The favicon was created on favicon-generator.
- This project was developed using the Boutique Ado project tutorial as a reference and guide. The code has been customised to fit the purpose of the project.
Product Images and content.
This site is a fictitious e-commerce store built for education purposes. The product images and descriptions however were taken from the following surf stores.
Media
The surfing images for the site were found through Google images in the following loactions.
- Surf lesson 1 - https://www.wavehunters.co.uk/
- Surf lesson 2 - https://tilegitsurf.com/en/surf-lessons-tenerife/
- Surf lesson 3 - http://sennenbeach.com/surf-lessons/
- Surf lesson 4 - https://soulsurfschool.com.au/byron-bay-surf-school-private-surfing-lessons/
- Surfing Image 1 - https://www.wavehunters.co.uk/
- Surfing Image 2 - https://www.surfline.com/surf-news/
- Surfing Image 3 - https://www.boardshop.co.uk/blog/mid-length-surfboards/
- Surfing Image 4 - https://www.helpfulholidays.co.uk/blog/10-cornish-beaches-for-surfing/
- Blog image 1 - https://www.stevens.edu/news/new-effort-harvest-sustainable-renewable-energy-ocean-waves
- Blog image 2 - https://www.livescience.com/38163-where-beach-sand-comes-from.html
- Blog image 3 - https://www.rnz.co.nz/news/sport/366883/paige-hareb-closes-in-on-medal-at-world-surfing-games
- Surf wipeout - https://www.booksurfcamps.com/news/surfing-wipeout
Acknowledgements
- To my wife Claire Parker for helping me test the app.
- To my mentor Reuben Ferrante for once again guiding me through this project, and being a fantastic mentor throughout this whole process.