crazycooky77 / ci_project5

0 stars 1 forks source link

NutriForce B2C Online Shop

NutriForce is a B2C online shop for sports and health nutrition in Ireland. The main purpose of the site is to enable the developer's friend to set up shop, as has been planned over a longer period of time. The reason for this is so that customers in Ireland can have a small, local business to support when it comes to their nutritional needs. High quality products will be sourced to build a loyal customer-base that trusts in the shop. A long-standing dream will come to fruition with the launch of this online shop, and we hope to provide customers with all the sports and health nutrition they need, as well as personalised, and excellent customer service. This can be become the one-stop-shop for anyone regularly purchasing such products, as requests will also be accepted, where we will aim to source the products, wherever possible. Welcome to the NutriForce family! Thank you for helping to make this dream possible!

Am I Responsive Image
  1. Web Marketing
    1. Target Audience
    2. Newsletter
    3. Facebook Page
    4. SEO
    5. Informational Pages
      1. About
      2. Shipping
      3. Returns
      4. Privacy Policy
      5. Terms & Conditions
      6. Support
  2. User Experience
    1. Visitor Goals
      1. First-Time Visitor Goals
      2. Returning Visitor Goals
      3. Frequent Visitor Goals
    2. User Stories
    3. Design
      1. Colour Palette
      2. Typography
      3. Imagery
    4. Site Planning
      1. Entity-Relationship Diagram
      2. Wireframes
        1. Login/Create Account
        2. Profile Pages
        3. Product Pages
        4. Checkout
  3. Features
    1. Feature Details
    2. Future Features
  4. Technologies
  5. Testing
    1. Manual Testing
    2. Automated Testing
    3. Validator Testing
      1. HTML
      2. CSS
      3. JSHint
      4. PEP8
      5. WAVE
      6. Lighthouse
    4. Bugs
      1. Fixed Bugs
        1. Product Sorting
        2. Safari
        3. Android
        4. Modals
        5. Miscellaneous
      2. Remaining Bugs
  6. Deployment
    1. Heroku
    2. ElephantSQL
    3. PyCharm
    4. Django Project
    5. Important Extras
  7. Credits
    1. Site Content
    2. Database Objects
    3. JSON Data
    4. Sorting and Filtering
    5. POST Requests
    6. Miscellaneous Django/Python
    7. Miscellaneous JavaScript
    8. Miscellaneous CSS

Web Marketing

Target Audience

The target audience is any adult interested in sports, and/or their health within Ireland. Whether they are just starting out, or experienced with their nutrition, NutriForce can help with suggestions, recommendations, or even sourcing a customer's favourite products, if not already in stock on the site.

The shop only has an online presence, but ensures to let customers know that it's a small, local business, using the keywords on the site, as well as the information on the About Us page. With shopping local becoming increasingly important worldwide, it's imperative the target audience is made aware of who they are buying their nutritional products from. Due to the planned scale of the business, the shop only allows addresses in Ireland for orders.

Pricing for products on the site will be competitive, as there are many large companies selling such products. While a slight increase to big box store prices is typically acceptable for customers interested in shopping locally, if the prices are too high, the benefits of using a small business will not be enough to attract and keep customers.

Newsletter

A newsletter signup link is available on every page of the site. The prominent but unobtrusive display of this feature makes it easy for customers to make use of it, without being bothered by it. When a customer signs up, a confirmation email is sent out to the email address used. This helps to ensure no one's email is used or stored for this, without their consent (in case someone uses an email address that does not belong to them). The confirmation email includes a link to unsubscribe from the mailing list that can be used at any time. If the email address used is linked to a registered account, the customer can also unsubscribe from their Profile at any time as well.

Privacy and customer experience concerns aside, the newsletter is used to promote special deals and new products, which should help entice some customers to make additional purchases.

See details and screenshots in the Feature Details section. Newsletter and Automated Emails > Customer Newsletter.

Facebook Page

A social media presence is critical for any business in current times. A mock-up Facebook page was created for the business that can be viewed below. An actual business page already exists, created by the business owner, but has not been used for this project. It is also not yet complete.

Mock-up Facebook page

SEO

For search engine optimisation, the following keywords are used in the site's metadata, and where reasonable, on various pages throughout the site:

These were identified based on the products being sold, typical search terms, our target audience, and typical business profile (small/local business based in Cork selling specifically in Ireland).

robots.txt and sitemap.xml files were created to ensure search engines know which pages should be accessed on the site. This helps improve site ratings, and hopefully the site's presence in search engine search results.

Informational Pages

Additional pages - all in the site footer - were created to ensure customers have all the necessary information about the company, their data and it's usage, and orders. Everything below in this section will help show customers that this is a trusted site they can make purchases from, as we are transparent, and all information is readily available. The Shipping, Returns, Privacy, and Support pages additionally include details on how to get in touch with the support team, should the customers need this.

See details and an example screenshot in the Feature Details > Information Pages section.

About

This page gives an introduction about the company and what is important to us. It should help customers feel more connected to us, and hopefully instill some confidence, as our values greatly relate to quality and integrity, as stated on the page.

Shipping

The Shipping detail page is currently rather generic, but will be updated once the shop officially goes live. For now, basic information is available to customers on the free shipping limit, shipping methods and times, and delayed orders.

Returns

This page details information on returns and refunds, again so customers don't have to search for this and have it readily available. The page ensures customers have the information necessary for them to know according to their rights, when a refund or return is required.

Privacy Policy

Details regarding what data is collected from customers and how it is used is fully outlined on this page. This is critical, particularly with the site being not only available in the EU, but specifically selling in Ireland (EU).

Terms & Conditions

A page outlining the full T&C for the site is available.

Support

A page specifically for customers to access support details was created, in case of users with strict security settings, who may not get the JavaScript modal pop-ups used in various areas on the site. While there is a "Support" link at the top of the page already, this is for the aforementioned JavaScript modal. The Support page and footer link were added as a backup. This way, any customer should be able to access support details, no matter what.

User Experience

Visitor Goals

Screenshots and more details on the features implemented to achieve the visitor goals are available in the Feature Details section.

First-Time Visitor Goals

Returning Visitor Goals

Frequent Visitor Goals

* Save for Later and Watchlist features are not yet implemented. This is planned for release 1.1.

User Stories

All completed EPICs and related user stories are listed in the repository Issues here.

Design

Colour Palette

Colour palette for the site

Typography

The Montserrat Google font is used throughout the site.

Imagery

Bing AI was used to create the logo, default product, and favicon images on the site. It was also used for the banner and "liked by" profile images in the Facebook page mockup.

Site Planning

Entity-Relationship Diagram

Colour palette for the site

Wireframes

Wireframes were used to plan out the pages for the site. Minor adjustments were made throughout, as the pages were being created. The navigation menu was reorganised in the final site iteration, and differs from the wireframes below as follows:

  1. The Newsletter Signup option was added next to the Support Contact details and both are now above the search bar
  2. A "Home" button was added to the main navigation bar.
  3. The site logo and customer action buttons (view cart, log in, create account) have swapped sides
  4. The customer action buttons all have icons added (instead of only the Cart button)
  5. A Support page was added, and is now linked in the site footer
Login / Create Account

Login: _Social media signup options have not yet been implemented. This is planned for release 1.1. See user story here._

Log in page wireframe

Create Account: _Social media signup options have not yet been implemented. This is planned for release 1.1. See user story here._

Create account wireframe

Profile Pages

Account Details:

Profile account details wireframe

Addresses: The Add New Address (now Add Address) button was moved, but otherwise the style has stayed the same.

Profile addresses wireframe

Orders:

Profile orders wireframe

Order Details:

Profile order details wireframe

Saved Items: _Saved Items have not yet been implemented. Therefore, the menu item (on the left) and the page itself is not yet available. This is planned for release 1.1. See user story here._

Profile saved items wireframe

Watchlist: _The Watchlist has not yet been implemented. Therefore, the menu item (on the left) and the page itself is not yet available. This is planned for release 1.1. See user story here._

Profile watchlist wireframe

Product Pages

Homepage (Featured Products):

Homepage (Featured Products) wireframe

Product Browser:

Product browser wireframe

Product Page: _Save for Later/Add to Watchlist is not yet available. This is planned for release 1.1. See user story here._

Product page wireframe

Checkout

Cart: _Save for Later is not currently available. This is planned for release 1.1. See user story here._

Cart view wireframe

Login / Guest Checkout: _This view was slightly updated. Social media login options are not available (planned for 1.1), Forgot Password was added to the login section, and Create Account was added below Login as an option._

Checkout login and guest checkout wireframe

Addresses: A "Back to Cart" button was added at the bottom left of this page.

Checkout addresses wireframe

Payment Options: _This page was completely removed. Also, only stripe payment is currently available. Additional payment options (GooglePay, Apple Pay, and PayPal) are planned for release 1.1._

Payment options wireframe

Confirmation: Show/Hide Cart and Edit Address links were added to this page. A Note to Seller is now also available at checkout. Text indicating that the customer will be charged once they confirm the purchase is now present. Finally, a "Back to Cart" button was added at the bottom left of this page.

Checkout confirmation wireframe

Features

All user stories, features, and bugs are listed in the repository's projects. For release 1.0, the kanban board can be found here. Completed and postponed (Cancelled) features are outlined in the board.

Some additional unplanned minor features have been implemented, not outlined in user stories/features, to promote customer satisfaction and loyalty, such as mailto links with predefined email subjects and bodies, where customers can request products be stocked, that are not in the database. These features are still outlined below as well.

Feature Details

Back to top

When a user scrolls down on any page on the site, a "Back to top" link will appear on the right side of the footer. When a customer clicks this, it will bring them to the top of the page again. This should make for easier site navigation, particularly on pages with a lot of content (e.g. the All Products page).

Back to top feature

Modals

JavaScript modals are implemented throughout the site to provide support details to customers. As mailto links opening are dependent on a user's browser and system settings, relying solely on these would cause problems for some customers. Therefore, modals were implemented to display the mailto link, as well as the plain-text support email address. Huge thanks to my mentor for identifying this issue and providing the suggestion.

(Mailto) modals

Newsletter

The related user story is here. The site has a newsletter signup button, that sends an email confirmation to the address entered. This way, if someone's email is used without their knowledge, or if they just no longer want to be subscribed, they can directly unsubscribe using the link in that same email. Customers can be kept up-to-date on new promotions and products via the newsletter.

Newsletter

Account Creation

Customers can create an account, so they can save and view their addresses, cart contents, and orders (user story).

Account Creation

Profile

The profile page offers various features for customers. They can change the email and/or password associated with their account. They can completely delete their account from the database. Addresses can be saved to the account, and those can be edited or deleted. Lastly, customers can view all their orders and the order details for each, such as order status and tracking links.

User stories for these features are below:

Products

Main categories (Sports, Health) are available for customers to browse products specific to their needs via the navigation bar. Dropdowns are available for sizes, and if applicable, flavours, for each product. The price displayed for the product immediately updates, depending on the size/flavour selected. Customers can then set a quantity for how much of the product they want, and add it to their cart (user story). Product pages include links to expand the description and ingredients for the products. This way, space on the page is saved. The user story for product details is here. Lastly, product pages also include a list of similar items, if available. These are determined by matching sub-categories for the products. The user story for linked products is here.

Product options

Product Sorting

All navigation bar product view options (All Products, Sports, Health, What's New) offer a button to sort/filter the products on the page by Brand, Product (name), Price, and On Sale products. This should make it easier for customers to find what they're looking for, while browsing.

Product sorting

Product Search

A search bar is available at the top of the site, so customers can search for products. This function looks for partial matches to brand names, product names, or flavours. If a flavour is searched, the relevant dropdown is pre-selected, if the flavour is in-stock.

Product search

Cart

If a customer is logged in, products added to cart will be added to both the session cart, and the SavedItems Django model for their account cart. The contents of the account cart are always available and saved until the customer empties it, or checks out. If not logged in, contents are just added to the session cart. Various features are available in the cart view:

Cart Merge

When logging in on any page except during checkout, if the customer has products in their session cart that they don't already have saved to their account cart, the session cart products will be added to the account cart.

Cart merge

Checkout

The user story for checkouts is here. Customers can check out as a guest, or while logged in. Doing so while logged in provides some useful features, such as being able to used saved addresses, and having their order saved to their account for later viewing.

Checkout Sign-in

Checkout Addresses

A "Same as Shipping" feature is available for all customers during checkout, to match their billing with their entered shipping address. When logged in, if addresses are saved to the account, the address form is autofilled with the default address, if available, and otherwise the most recently saved address. A dropdown is available to select any address saved to the account, which will autofill the form with the newly selected address details. The dropdown also includes a "New Address" option to clear the form, so the customer can enter new details without having to manually delete the autofilled address first.


Checkout Addresses View
Checkout Addresses
Saved Address Selection
Checkout Address selection

Checkout Cart

At the last checkout page to confirm the purchase, a "Show/Hide Cart" feature is available. By default, the cart contents are not displayed, only the cart totals, to save space and show a cleaner, less-busy overview.

Show/Hide Cart at Checkout

Information Pages

While not exactly a feature, the informational pages on the site, linked in the footer, serve to provide customers with details they may need to common questions or problems. They help promote trust in the site, and ensure that customers can receive the support they need, for any possible issue.

Informational pages

Automated Emails

Verification and confirmation emails are automatically sent by the system for various features. These are sent to customers to ensure they have all the necessary information for various actions. There are also some that are sent to the admin of the site, where action may be required of them.

Some example screenshots have been added below.


Customer Newsletter
Newsletter email
Customer Order Confirmation
Order confirmation email
Admin New Order
New order email
Admin Order Error
Order error email
Admin Server Error
Server error email

Responsive Design

The user story for mobile views is here. Based on the customer's screen width, various parts of the website are adjusted to better utilise the available space. The main changes between larger and smaller screens are that text is updated to icons or shorter text, and lesser-important information is removed from tables. Specifically:


Responsive Design - Large Screens
Left navigation menu
Large screen left nav
Center navigation menu
Large screen nav menu
Profile menu
Large screen profile menu
Orders table headers
Large screen order table headers
Order details table headers and product image
Large screen order details headers
Cart table headers and product image
Large screen cart headers
Responsive Design - Small Screens
Left navigation menu with hover-text
Small screen left nav
Center navigation menu
Small screen nav menu
Profile menu

Show/hide the box with links via clicking "Menu".

Small screen profile menu
Orders table icons
Small screen order table headers
Order details table icons
Small screen order details headers
Cart table icons
Small screen cart headers

Admin Panel

An admin panel is available for the site owner to view, edit, create, and delete any contents in/from the database. The Django Admin Panel is fully sufficient for this purpose, so no custom views or functionality were included, beyond special sorting for products. The admin panel cannot be accessed by standard user accounts. Related user stories are:

Admin Panel

Future Features

For release 1.1, the kanban board is here. Postponed User Stories from 1.0 are planned for release 1.1, as well as enhancements and minor bugs identified during initial project release. They can also be found in the repository's Issues. Enhancements are labelled with "enhancement" and the postponed user stories are labelled with "user-story".

Technologies

Testing

Manual Testing

All "Inspector" tests were conducted in Chrome on macOS.

Function

__

Expectation

___

MacOS Safari

__

iOS Safari

__

iPadOS Chrome

__

Windows 11 Edge

__

Windows 11 Chrome

__

AndroidOS Chrome

_____

Inspector > 1100px

_____

Inspector < 1100px

_____

Inspector < 800px

_____

Inspector < 500px

_____

Inspector < 320px

_____
JavaScript mailto modals These are used on various pages throughout the site. "click here" in the modal text is a mailto link. It should open a draft email to the support contact email in the local mail client. Depending on the scenario, the draft email will also have an auto-filled email subject and email body. Clicking the email address in the modal text should copy it to clipboard and show a "Copied!" message below the text. The modal itself and/or the mailto link may not work, depending on user's browser and system settings, e.g. blocked pop-ups.
csrf errors - view Any csrf errors on the site should direct to the custom view.
csrf errors - email to admin csrf errors should send an email to the admin.
csrf errors - modal The custom csrf error text should have a link in the text that opens a mailto modal.
404 errors - view Any 404 errors on the site should direct to the custom view.
404 errors - modal The custom 404 error text should have a link in the text that opens a mailto modal.
500 server errors - view Server errors (500) should direct to the custom view.
500 server errors - email to admin Server errors (500) should send an email to the admin.
500 server errors - modal Th custom 500 error text should have a link in the text that opens a mailto modal.
Footer - Back to top function Button should be hidden until user scrolls down. Button should then appear. Onclick, user should be brought to the top of the page.
Footer - Support Support link in the footer should bring the user to the Support view. This is a backup for user systems/settings that can't display the JavaScript modal and mailto links.
Footer - About page About link in footer should bring the user to the About Us view.
Footer - Privacy page Privacy link in footer should bring the user to the Privacy Policy view.
Footer - Returns page Returns link in footer should bring the user to the Returns and Refunds view.
Footer - Shipping page Shipping link in footer should bring the user to the Shipping Information view.
Footer - T&C page Terms & Conditions link in footer should bring the user to the T&C view.
Footer - Facebook link Facebook (Follow Us) link in footer should bring the user to the external Facebook page for the business.
Navigation bar - desktop sizing Nav bar for widths > 1100px should display with both text and icons for the nav-left, and larger center nav buttons. N/A N/A N/A
Navigation bar - larger screen sizing Widths < 1100px should reduce the center nav button padding. N/A N/A
Navigation bar - mid-screen sizing Widths < 800px should remove text from the nav-left to leave only icons, and change center nav button text to shortened versions. N/A N/A N/A
Navigation bar - small-screen sizing Widths < 500px should reduce center button padding further and reduce overall font size. N/A
Navigation bar - smallest screen sizing Widths < 320px change the top middle links (newsletter and support) to colum flex-direction and reduce paddings and margins. N/A N/A N/A
Support - link and modal When clicking the link, a mailto modal should open with support contact details.
Newsletter signup - modal Clicking the Newsletter Signup link should open a modal asking the user to enter their email address and provide a "Subscribe" button.
Newsletter signup - empty input Empty inputs should show an error to the user (on the current page, not in the modal).
Newsletter signup - invalid input Inputs without "@" should show an error from the input field, that the email address is missing an "@". Inputs with an "@" but without the top-level domain should show an error to the user (on the current page, not in the modal).
Newsletter signup - successful Entering a valid email address should add the email to the Django Newsletter model and show a message to the user confirming successful sign-up.
Newsletter signup - already subscribed If the user tries to subscribe with an email address already in the Django Newsletter model, they should receive a message that they're already subscribed.
Newsletter signup - confirmation email to user After successfully signing up to the newsletter, the user should receive a confirmation email that includes an unsubscribe link.
Newsletter signup - unsubscribe from confirmation email link Clicking the unsubscribe link in newsletter confirmation or other emails should remove the email address from the Django Newsletter model and display a success message to the user on a specific unsubscribe page.
Newsletter signup - unsubscribe errors and modal There are custom error messages for various scenarios. 1) User already unsubscribed previously (with mailto modal to contact support, if needed). 2) Link formatted incorrectly. 3) Link accessed manually (no POST request).
Login - account doesn't exist Trying to log in with an email address that is not registered, should display an error that the email/password is incorrect.
Login - invalid credentials Logging in with the incorrect password should display an error that the email/password is incorrect.
Login - successful A successful login should display a success message for the user and redirect to the homepage.
Login page - logged in Accessing the login page when already logged in should immediately redirect to the homepage.
Logout Logging out should display a success message for the user and redirect to the homepage.
Logo link Clicking in the logo, which is wrapped in an anchor link, should load the homepage.
Password reset - errors Email validation is in place for the password reset view. Errors should appear from the input for empty inputs or inputs without an "@". An error should appear on the page for invalid email addresses (top-level domain missing).
Password reset - link requested - success A message should display for the user to confirm they were sent an email.
Password reset - link requested - error If the user accesses the page following any link except for the /password/reset, an error should be displayed with links to the Forgot Password page on the site. A mailto modal should also be included in the text to contact support, if needed.
Password reset - email - account exists The user should receive an email with a custom password reset link after successfully requesting a password reset for an existing account.
Password reset - email - account does not exist Trying to reset the password using an email address that is not yet registered should result in an email to that address stating that the account does not exist, and include the account signup link.
Password reset - link error If the user accesses an invalid link (e.g. expired/already used), they should receive a corresponding error message that includes a link to the forgot password form.
Password reset - link valid When the user clicks a valid password reset link from their email, they should encounter a page to change the password for their account.
Password reset - password change invalid If the user enters a password that does not the meet the minimum requirements, they should receive an error message.
Password reset - password change successful If the user enters a password that meets minimum password requirements, they should be automatically logged in, receive a success message for the changed password and login, and be redirected to the homepage.
Password reset pages - logged in When accessing any password reset pages while logged in, the user should receive a message that they're already logged in and can change their password from their Profile instead.
Account creation - email invalid Input errors should appear for empty email address inputs or emails entered without "@". An error will appear on the page for otherwise invalid email addresses (e.g. missing top-level domain).
Account creation - email exists When trying to sign up using an email address that is already registered, the user should see a message to verify their email address. The email sent should indicate that an account already exists, and provide a password reset link.
Account creation - password invalid The user should receive an error when using a password that does not meet the minimum requirements.
Account creation - successful After successfully entering an email and password for account creation, the user should receive a message to verify their email address.
Account creation - email verification valid link When a user clicks a valid email verification link for creating an account, they should be brought to the login page with a message that their email address is confirmed.
Account creation - email verification invalid link When a user clicks an invalid link, they should receive a message that the link is expired and to issue a new one, if needed.
Account creation -logged in Accessing the signup page when logged in should redirect to the homepage.
Profile - menu - larger screens Screen widths > 800px should display text links on the left side of each profile page to navigate between the profile pages. N/A N/A
Profile - menu - smaller screens Screen widths < 800px should display just a "Menu" link at the top of each profile page, that expands to show the links to the different profile pages for navigation. N/A
Profile - account details Accessing the main profile page should display account details - the user's email address, and buttons to change their email/password, unsubscribe from the newsletter (if subscribed), and delete their account.
Profile - unsubscribe from newsletter via profile Clicking the button to unsubscribe should immediately remove the user's email address from the Django Newsletters model, and confirm to the user that they are unsubscribed.
Profile - delete account with modal Clicking the delete account button should open a modal, asking the user to confirm account deletion, as this cannot be undone. Once confirmed, the user should be deleted from the Django Users model.
Profile - email change - email invalid An error message should appear when entering an empty/invalid email address.
Profile - email change - email exists An error should appear that the email is already registered to another account (or "this" account, if it's the same email address as the logged in user), when trying to use an email address linked to another user.
Profile - email change - pending verification After submitting a valid email address, the user should receive a message that a verification email has been sent. Accessing the email change view while an email change is pending should display both email addresses (current and changing to), a message for the pending verification, and a button to re-send the verification email.
Profile - email change - re-send verification Using the re-send verification button on the email change page during a pending change, should result in a new verification email being sent out, along with a confirmation message to the user.
Profile - email change - email verification valid Clicking a valid email verification link should display a message for the user to confirm the email address was verified.
Profile - email change - email verification invalid Using an invalid (e.g already used) email verification link should provide an error that it's invalid/expired, and advise to issue a new email confirmation request.
Profile - email change - successful After clicking a valid email verification link, the email address for the account in the Django Users model should be updated, and the user should be able to log in with the new email address and same password.
Profile - email change - cancel pending change Canceling an email change should remove the email address pending verification from the user's email change profile view and enable them to start a new email change process.
Profile - password change - current password invalid An error should appear asking the user to type their current password, if they enter an incorrect one.
Profile - password change - new password invalid If the user enters a new password that does not meet the minimum requirements, they should receive an error message accordingly.
Profile - password change - successful If the user enters a valid current and new password, they should receive a message that their password was successfully changed, and only be able to log in with their new password.
Profile - addresses - no addresses For user accounts with no saved addresses, the Default and Other Address(es) columns should be displayed, with only an Add Address button under Default Address.
Profile - addresses - only non-default address For user accounts with only Other Addresses, and no default, the list of Other Addresses should be displayed, with Make Default, Edit Address, and Delete Address buttons for each. The Add Address button should be displayed under the Default Address header.
Profile - addresses - only default address For user accounts with only a default address, the Other Addresses column should be empty of addresses. The default address should be displayed under the Default Address header, along with an Edit Address button. An Add Address button should be displayed under the Other Addresses header.
Profile - addresses - default and other addresses If the user account has both default and other addresses, the default address should be displayed with an Edit Address button. Add Address should be displayed right under the Other Addresses header, and below that button, the non-default saved addresses should be displayed, with the Make Default, Edit Address, and Delete Address buttons.
Profile - addresses - make default Make Default should move the current default address (if applicable) to Other Addresses, and the address above the Make Default button to the Default Address. The user should receive a success message.
Profile - addresses - delete address Delete Address should delete the address above the clicked button from the account. The user should receive a success message. The message will either indicate that the address was completely deleted (backend: from the user account and the Django Addresses model). Or that the address was only deleted from their account, but still exists in the system, as an order is associated with it. In this case, the user is just deleted from that column in the Django Addresses model.
Profile - addresses - add address - missing required field An input error should indicate a missing required field, if applicable.
Profile - addresses - add address - successful non-default Adding a non-default address to the account should redirect the user to the main profile addresses page, provide a success message, and display the new address in the Other Addresses list, along with the others (if applicable).
Profile - addresses - add address - successful default Adding a default address to the account should remove the default flag from the previous default address (if applicable), redirect the user to the main profile addresses page, provide a success message, display the new address under Default Address, and display the previous default under Other Addresses (if applicable).
Profile - addresses - edit address - invalid address ID If the address ID in the URL is invalid for addresses for the logged-in user, a custom error should appear.
Profile - addresses - edit address - missing required field An input error should indicate a missing required field, if applicable.
Profile - addresses - edit address - successful non-default Editing an address as non-default should redirect the user to the main profile addresses page, provide a success message, and display the updated address in the Other Addresses list, along with the others (if applicable).
Profile - addresses - edit address - successful default Editing an address as default should remove the default flag from the previous default address (if applicable), redirect the user to the main profile addresses page, provide a success message, display the updated address under Default Address, and display the previous default under Other Addresses (if applicable).
Profile - orders - no orders A message advising that there are no orders to display should be shown.
Profile - orders - with order(s) A list of (limited) order information should be displayed for each order linked to the account. Each order should also have a button to view the details for that order.
Profile - orders - with orders(s) - larger screens Screen widths > 1100px should display text headers for the list of order information. N/A N/A
Profile - orders - with order(s) - smaller screens Screen widths < 1100px should display icons instead of text headers. Widths < 500px should additional update the "View Order" button text to "View".
Profile - orders - order details The basic order information should be displayed, as well as a table below that to display details for the products purchased, and prices for the order.
Profile - orders - order details - invalid ID If the order ID in the URL is invalid for orders for the logged-in user, a custom error should appear.
Profile - orders - order details - larger screens Screen widths > 1100px should display text headers for the list of order information. N/A N/A N/A
Profile - orders - order details - smaller screens Screen widths < 1100px should display icons instead of text headers. Screen widths < 800px should additionally completely remove the product image, and the "Individual Price" column from the purchased product details.
Profile - orders - order details - status pending/processing/ready Orders with pending, processing, or ready to ship status should display a Request Cancellation button in the order information. This button displays a mailto modal, that includes custom email subject/body content.
Profile - orders - order details - status shipped/delivered Orders with shipped or delivered status should display a Request Refund button in the order information. This button displays a mailto modal, that includes custom email subject/body content.
Profile - orders - order details - without tracking Orders without a tracking link in the database should display "N/A" in the tracking column.
Profile - orders - order details - with tracking Orders with a tracking link should display linked "Track" text that, when clicked, opens the shipping provider's page to display tracking information.
Profile pages - logged out Trying to access any profile pages while logged out should display a message that the user needs to log in to view the page.
Homepage - featured products The homepage should display 1 new featured product, 1 featured sports product, and 1 featured health product. All 3 should be different products (no overlap with new and sports/health). All should have in-stock options. Where no featured product is available for a certain category, a message should be displayed to that effect.
Homepage - out of stock flavours/sizes Out of stock options should be greyed out.
Homepage - product link Clicking the product image/name should open the individual product page.
Homepage - add to cart Adding a product to cart should display a Django message with a link to View Cart.
All products - view Accessing the All Products view should display all active products. By default, they are sorted by descending stock count. Where no active products are available, a message should be displayed to that effect.
All products - out of stock flavours/sizes Out of stock options should be greyed out.
All products - fully out of stock Products where all flavours and sizes are out of stock should hide the select dropdowns and add to cart feature, and only display "Out Of Stock" text below the product image and name.
All products - product link Clicking on the product image/name should open the individual product page.
All products - add to cart Adding a product to cart should display a Django message with a link to View Cart.
All products - sorting Using the sort menu should sort and display the products according to the option selected. All products should still be displayed (except for the On Sale sort option).
Sports products - view Accessing the Sports Products view should display all active products with the main category "sports. By default, they are sorted by descending stock count. Where no sports products are available, a message should be displayed to that effect.
Sports products - out of stock flavours/sizes Out of stock options should be greyed out.
Sports products - fully out of stock Products where all flavours and sizes are out of stock should hide the select dropdowns and add to cart feature, and only display "Out Of Stock" text below the product image and name.
Sports products - product link Clicking on the product image/name should open the individual product page.
Sports products - add to cart Adding a product to cart should display a Django message with a link to View Cart.
Sports products - sorting Using the sort menu should sort and display the products according to the option selected. All sports products should still be displayed (except for the On Sale sort option).
Health products - view Accessing the Health Products view should display all active products with the main category "health". By default, they are sorted by descending stock count. Where no health products are available, a message should be displayed to that effect.
Health products - out of stock flavours/sizes Out of stock options should be greyed out.Using the sort menu should sort and display the products according to the option selected. All products should still be displayed (except for the On Sale option).
Health products - fully out of stock Products where all flavours and sizes are out of stock should hide the select dropdowns and add to cart feature, and only display "Out Of Stock" text below the product image and name.
Health products - product link Clicking on the product image/name should open the individual product page.
Health products - add to cart Adding a product to cart should display a Django message with a link to View Cart.
Health products - sorting Using the sort menu should sort and display the products according to the option selected. All health products should still be displayed (except for the On Sale sort option).
New products - view Accessing the What's New view should display all active products that were added to the database in the last 30 days. By default, they are sorted by descending stock count. Where no new products are available, a message should be displayed to that effect.
New products - out of stock flavours/sizes Out of stock options should be greyed out.
New products - product link Clicking on the product image/name should open the individual product page.
New products - add to cart Adding a product to cart should display a Django message with a link to View Cart.
New products - sorting Using the sort menu should sort and display the products according to the option selected. All new products should still be displayed (except for the On Sale sort option).
Sorting - Brand A-Z Using the Brand A-Z sort should ascending sort all products on the page by the product brand name.
Sorting - Brand Z-A Using the Brand Z-A sort should descending sort all products on the page by the product brand name.
Sorting - Product A-Z Using the Product A-Z sort should ascending sort all products on the page by the product name.
Sorting - Product Z-A Using the Product Z-A sort should descending sort all products on the page by the product name.
Sorting - Price Low to High Using the Price Low-High sort should ascending sort all products on the page by the product price. It should sort any in-stock option, not just the auto- or user-selected ones. Fully out of stock products will no longer be visible, as they don't have a price.
Sorting - Price High to Low Using the Price High-Low sort should descending sort all products on the page by the product price. It should sort any in-stock option, not just the auto- or user-selected ones. Fully out of stock products will no longer be visible, as they don't have a price.
Sorting - On Sale Using the On Sale sort option is actually filter and should only display products with the sale boolean set to true in the database. Where no products are on sale, a message should be displayed to that effect.
Sorting - add to cart After adding a product to the cart from a sorted view, the sorting should persist until they load a new page (or refresh the current one).
Product search - empty input If the user submits an empty search, they should receive a message that an empty search term was used.
Product search - no results If no product brands, names, or flavours in the database match the search term, the user should receive a message to that effect.
Product search - no results - modal functions The message for no results following a product search includes a mailto modal link. The mailto for this scenario includes a pre-filled email subject and body.
Product search - brand/name results A successful search for a product brand or name should display the results in a list similar to the existing product pages, along with a message displaying the searched term.
Product search - flavour results In addition to the functionality used for brand/name search results, a successful flavour search should automatically select the searched flavour in the displayed results (if in stock).
Product search - add to cart After adding a product to the cart from a search results view, the results list should persist until they load a new page or make a new search.
Product search - sorting Using the sort menu should sort and display the products according to the option selected. All new products should still be displayed (except for the On Sale sort option).
Product page - view The individual product page should display the relevant product, detailed product information, and a list of linked products, if applicable.
Product page - out of stock flavours/sizes Out of stock options should be greyed out.
Product page - fully out of stock The product flavour (if applicable), size, price, quantity, and add to cart should all be hidden, if nothing is in stock. The "Availability" text should update to include "Out Of Stock".
Product page - add to cart Adding a product to cart should display a Django message with a link to View Cart.
Product page - show/hide description Clicking the Show/Hide description button should display or hide the description for the product.
Product page - show/hide ingredients Clicking the Show/Hide ingredients button should display or hide the ingredients for the product.
Product page - no linked products The entire linked product section, with the "you may also like..." text should be hidden, if there are none.
Product page - linked products In-stock products that share categories with the individual product page product should be listed in the linked products section at the bottom of the page. Product details and add to cart options should be visible and functional for each linked product.
Product page - linked products - out of stock flavours/sizes Out of stock options should not be displayed at all.
Product page - linked products - add to cart Adding a product to cart should display a Django message with a link to View Cart.
Add to cart - single product When successfully adding a single product to the cart, a success message should appear for the user, using the singular "product".
Add to cart - multiple products When successfully adding a multiple products to the cart at a time, a success message should appear for the user, using the plural "products".
Add to cart - stock exceeded - nothing added When adding a product to the cart where the user already has the maximum available stock of that same product in their cart, a Django message should appear that the product could not be added, and why.
Add to cart - stock exceeded - maximum added (multiple) If the total quantity for a product in the user's cart plus the quantity they want to add for the same product, exceeds the stock, the maximum possible amount will be added, with a message explaining this to the user (using plural terminology).
Add to cart - stock exceeded - maximum added (single) If the total quantity for a product in the user's cart plus the quantity they want to add for the same product, exceeds the stock, the maximum possible amount will be added, with a message explaining this to the user (using singular terminology).
Add to cart - view cart link After trying to add a product to the cart, the Django message should include a link for the user to click to view their cart.
Guest and account carts If not logged in, the user's cart contents should be added to their Django session. Once cookies are cleared, for any reason, the cart contents will be gone. If logged in, the user's cart contents should be saved to the Django SavedItems model. This data persists until the user deletes it, or completes the purchase.
Cart merge function - non-checkout When a user adds products to their cart when not logged in, and then logs in after, the cart contents from their Django session storage is merged with their SavedItems cart contents.
Cart merge function - checkout When a user logs in during the checkout process, carts should not be merged. The Django session cart should be used, and should overwrite the SavedItems cart.
Cart - with products The cart view should display product information and overall cart pricing. Below 800px screen width, the text headers are replaced by icons, and the product image and Individual Price column are removed.
Cart - product removed If a product is removed from the user's cart, due to stock changes, they should see a message to that effect when next accessing the cart.
Cart - stock changed for product If the quantity for a product in the user's cart is reduced, due to stock changes, they should see a message to that effect when next accessing the cart.
Cart - remove product from cart When the user removes a product from their cart (red X beside the quantity input), they should receive a message confirming the product was removed.
Cart - update cart (add/remove quantity) When a user clicks the "Update Cart" button, the current quantity for products should be updated in their session cart, and if logged in, their SavedItems cart. They should also receive a confirmation message that their cart was updated.
Cart - empty cart function and modal Clicking the Empty Cart button should display a modal for the user to confirm, as the action cannot be undone. Once confirmed, the full cart contents should be deleted from the Django session, and if logged in, also from the SavedItems model.
Checkout pages - back to cart All checkout pages (signin, addresses, confirm) should have a button that leaves the checkout process and loads the cart view on-click.
Checkout - signin - create account If not logged in, the first checkout page should display a button for the user to create an account, which takes them through the standard account signup flow and pages.
Checkout - signin - forgot password The initial checkout page when not logged in should include a forgot password password, that takes the user through the normal forgot password flow and pages.
Checkout - signin - login The initial checkout page when not logged in should display login fields. This login should include the standard checks for correct emails/passwords. Upon successful login, the user should be directed to the next checkout page (addresses).
Checkout - signin - guest checkout The initial checkout page when not logged in should display a guest checkout button, that lets the user access the second checkout page (addresses) without logging in.
Checkout - addresses - logged out The addresses checkout, when not logged in, should display 2 address forms - one for shipping, and oen for billing. Above the billing address form, a button for the same as shipping function should be displayed.
Checkout - addresses - logged in - saved addresses When logged in, the address checkout should show a dropdown for saved addresses linked to the user's account. If the account has no saved addresses linked, the view should be the same as when logged out.
Checkout - addresses - logged in - select saved address When selecting a saved address from the dropdown, the form data should auto-fill, based on the selected address.
Checkout - addresses - logged in - default saved address If the user has a saved address marked as default in their account, the form should have that address auto-filled when accessing the page.
Checkout - addresses - logged in - no default saved address If the user has saved addresses, but none are marked as default, the latest address added to the account should be auto-filled in the form.
Checkout - addresses - logged in - change autofilled input When a user edits an input with auto-filled content, the saved address dropdown should change from the originally selected address, to "Select Saved Address".
Checkout - addresses - logged in - new address function When the user selects "New Address" from the dropdown, it should empty all form input fields.
Checkout - addresses - same as shipping function Clicking the "Same as Shipping" button should copy all input values from the Shipping Address, to the Billing Address.
Checkout - addresses - missing required fields An input error should appear if the user does not fill in all required address fields.
Checkout - addresses - successful Successfully entering a shipping and billing address and clicking Next should bring the user to the last checkout page (confirm and purchase).
Checkout - confirm - show/hide cart function Clicking the Show/Hide Cart button should display and hide the product details in the cart. Totals (sub, shipping, grand) should always be visible.
Checkout - confirm - stock changes The user's cart contents should be checked against the product stock when accessing the confirm checkout page, and when clicking confirm purchase. Any cart changes should then be displayed in the cart section of the confirm checkout page.
Checkout - confirm - emptied cart If the user's cart is completely emptied during checkout, due to stock changes, they should be redirected back to the cart page, and see a message listing the issue and removed products.
Checkout - confirm - edit address function Using the Edit Address button on the confirm checkout page, should bring the user back to the address checkout page. However, the previously entered addresses should be autofilled in the form instead.
Checkout - confirm - note to seller Users can add a note to seller on teh confirm checkout page, that should be saved to the user's order, and PaymentIntent. When using the Edit Address function, the order note should be saved, and be autofilled when confirming the edited address and going back to the confirm checkout page.
Checkout - confirm - invalid card number Entering an invalid card number in the stripe input field should display an error.
Checkout - confirm - invalid expiry date Entering an invalid expiry date in the stripe input field should display an error.
Checkout - confirm - invalid post code format Entering an invalid post code format into the stripe input field should display an error.
Checkout - confirm - server error 500 (e.g. hosted endpoint off) If the hosted endpoint is offline, the user's payment should go through, but the webhook handler is unlikely to complete the other necessary actions to create the order in the database and send the user the confirmation email. In this case, they should receive a custom error to not make another purchase and that the support will be in touch.
Checkout - confirm - server error 500 - email to admin The admin should receive an email that the error occurred, so they can review it and, if necessary, re-send the webhook attempt to create the order and send the confirmation emails.
Checkout - confirm - successful For a successful checkout, the order details should be added to the Django OrderHistory model, and the individual products purchased to the Django Purchases model.
Checkout - success view The user should be directed a purchase confirmation page upon successful checkout. This page should display their purchased products, the totals for the order, their shipping and billing address, and their note to seller (if applicable).
Checkout - confirmation email to user After a successful purchase, the user should receive a confirmation email.
Checkout - confirmation email to admin After a successful purchase, the admin should receive a confirmation email, so they know to prepare the order.
Checkout - error view For any errors during checkout, or when trying to access the checkout/success page outside of the checkout flow, the user should see a custom error (for checkout issue, page refreshes, or accessing the link manually). For errors and refreshes, a mailto modal to contact support, if needed, should be linked in the text.

Automated Testing

Automated testing has not yet been implemented. This has been postponed to the 1.1 release.

Validator Testing

HTML

All pages were checked with Nu HTML Checker. Minor issues identified were resolved, and no errors or other warnings remain.

Nu HTML Checker passed

CSS

Contents of every CSS file validate using Jigsaw without errors.

W3C CSS Checker results

JSHint

All JavaScript files were checked using JSHint.

The below warnings from JSHint remain, but are not relevant, as per the provided comments:

  1. "undefined variables" mentioned are all from JQuery ($), the base.js file (prvWidth) that is pre-loaded separately, or the HTML file (json_addr)
  2. "unused variables" mentioned are all used in the HTML files as on-click functions
  3. Use ES10 for optional catch binding; catch binding works on the live site without issue
  4. Body of for should be wrapped in if; it is already wrapped in an if statement
  5. 3x Confusing semantics due to in-loop functions referencing outer-scoped variables; this is incorrect, the in-loop reference is to make updates related to that specific element

All other (syntax) issues were resolved.

  1. and 2. checkout.py (prvWidth is also used in products.py, addresses.py, orders.py, cart.py with the same warning): JSHint checkout warnings
  2. base.py: JSHint base warnings
  3. stripe.py: JSHint stripe warnings
  4. products.py: JSHint product warnings line 143
  5. products.py: JSHint product warnings lines 190 and 196 JSHint product warnings line 465

PEP8

All python files were checked using PEP8. The only errors are from Django default "AUTH_PASSWORD_VALIDATORS" in the settings.py file (lines too long).

PEP8 validator results

WAVE

WAVE was used on each page of the site. The majority of issues were contrast errors. Styling on the site was updated to alleviate this for better accessibility.

WAVE validator results

Lighthouse

All pages were checked using Lighthouse. Several minor performance issues (most notably on pages with a lot of scripts and/or images, such as All Products) are due to HTTP/1.1 requests, unused JavaScript (stripe), and render-blocking resources, that are all necessary. Amazon S3 does not support HTTP/2, so an enhancement was raised to potentially switch over to Amazon CloudFront, which additionally seems more cost-effective.

Homepage
Lighthouse homepage results
Signup
Lighthouse sign-up results
Signup - Confirmation Link Sent
Lighthouse sign-up email confirmation results
Signup - Invalid Confirmation Link
Lighthouse sign-up invalid confirmation link results
Login
Lighthouse login results
Forgot Password
Lighthouse password reset results
Forgot Password - Email Sent
Lighthouse password reset email sent results
Forgot Password - Invalid Link
Lighthouse password reset invalid link results
Forgot Password - Success (Change Password)
Lighthouse password reset change password results
Forgot Password - Logged In Error
Lighthouse password reset logged in error results
Profile Pages

Profile pages have an SEO score of only 91, due to the mobile menu being an uncrawlable link (javascript:void(0);).

Profile - Account Details
Lighthouse profile account details results
Profile - Email Change
Lighthouse profile email change results
Profile - Email Change Invalid Link
Lighthouse profile email change invalid link results
Profile - Password Change
Lighthouse profile password change results
Profile - Addresses
Lighthouse profile addresses results
Profile - Add Address
Lighthouse profile add address results
Profile - Edit Address
Lighthouse profile edit address results
Profile - Orders
Lighthouse profile orders results
Profile - Order Details
Lighthouse profile order details results
Profile - Logged Out Error
Lighthouse profile logged out error results
All Products
Lighthouse all products results
Sports
Lighthouse sports products results
Health
Lighthouse health products results
What's New
Lighthouse new products results
Product Search
Lighthouse product search results
Product Page
Lighthouse product page results
View Cart
Lighthouse view cart results
Checkout

All checkout pages share the same link, so Lighthouse could not evaluate them separately (always loads the checkout address page while Lighthouse is running).

Lighthouse checkout results
Checkout Complete
Lighthouse checkout complete results
Support
Lighthouse support page results
Privacy Policy
Lighthouse privacy policy page results
Terms & Conditions
Lighthouse T&C page results
About Us
Lighthouse about us page results
Returns
Lighthouse returns and refunds page results
Shipping
Lighthouse shipping page results
Newsletter Unsubscription
Lighthouse unsubscribed from newsletter results
404 Error Page
Lighthouse 404 error page results

Bugs

Fixed Bugs

Product Sorting

JavaScript product functionality is dependent on the select option dropdowns being sorted the same as the JavaScript JSON. A specific product flavour/size/stock combination helped identify an issue with inconsistent sorting, that led to incorrect/unexpected results being displayed on the page. This, and hopefully any other issues, were resolved by implementing/updating 2 sort functions. Near the start of the product scripts, the product select options on the page are sorted to match the JSON. Near the end, the product select options are sorted for aesthetics (alphabetically/ascending).

Safari

The main focus of fixes during testing were due to unique Safari browser behaviours, as the same features worked without issue in Chrome during development and testing.

Android

Android keyboards fire a window resize event, which caused some issues with JavaScript modals. All resize event listeners were updated to check for screen width* resizes instead (Android keyboards resize height only).

Modals

While not a bug, of particular note is that the JavaScript modals and mailto links throughout the site are dependent on the user's system and browser settings. This means that the mailto link may not open, and the entire modal may not even appear, for certain users. To help with this, an extra support page was added to the footer, with the support contact email. A link to that page was added to the texts that open the mailto modal, where possible. There are a few areas on the site, where users with strict security settings will still encounter issues, e.g. the Newsletter Signup, and any mailto modals linked specifically to buttons (e.g. order cancellation/refund requests). These users can, of course, still access the support page via the footer, and reach out manually.

Miscellaneous

Additional minor updates were made throughout testing, when it was determined that better styling or functionality would improve the user experience.

Remaining Bugs

Remaining unfixed bugs can be found in the kanban board for release 1.1 (prepended with [BUG]). Alternatively, in the repository's Issues using the "bug" label.

Deployment

The site was deployed on Heroku. ElephantSQL was used for the database, as end of life is only in January 2025. PyCharm and GitHub Desktop were used for local development.

Heroku

  1. Cloned the basic repository from Code Institute
    1. Code > Open with GitHub Desktop
  2. Created new repository in own GitHub for the cloned repository
  3. Created new app on Heroku
    1. New > Create new app
    2. Provide app name and select region > Create app
  4. Linked Heroku to cloned GitHub repository
    1. Click GitHub in the Deployment method section
    2. Log into GitHub, provide access to Heroku, and type in the repository name
    3. Search
    4. Connect
  5. Enabled automatic deploys
    1. Tick the box for Automatic deploys in the corresponding section
  6. Added python buildpack in the Settings > Buildpacks section
  7. Added necessary Config Vars

ElephantSQL

  1. Logged into ElephantSQL and Create New Instance
  2. Added a name for the instance
  3. Selected the Tiny Turtle (Free) plan (should be pre-selected)
  4. Selected Region (bottom right)
  5. Selected the closest Data center
  6. Reviewed selections and Create instance
  7. Opened the newly created instance
  8. Selected "ADMIN" in the left sidebar (not editable, but can be viewed)
  9. Under "Nodes", ensured the PostgreSQL version is 12+ (this is required for Django)
  10. Initially it was not, so deleted and recreated the instance to get a different Host assigned
    1. These seem to be randomly assigned, and each has a different PostgreSQL version installed
    2. For example, "kandula" will not work (version 11.9), but trumpet (13.9) and flora (15.4) will

PyCharm

  1. File > New Project
  2. Selected Django from the left sidebar
  3. Gave the project a name
  4. For Location, selected the local GitHub repository folder

Django Project

  1. Opened the Terminal in PyCharm (View > Tool Windows > Terminal)
  2. If not already installed: pip3 install django==4.2.1
  3. Created the Django project: django-admin startproject XX_PROJECT_NAME_XX .
  4. Created the gitignore file: touch .gitignore
  5. Added details as here
  6. python3 manage.py migrate for the initial migration
  7. Installed packages as in the requirements file
  8. Added necessary variables locally, as in Heroku
    1. PyCharm > Settings > Tools > Terminal > Environment variables
  9. Updated settings.py, e.g. for ALLOWED_HOSTS, DEBUG, DATABASES, and directories (static, media, and templates)
  10. Procfile created in the main folder for the Django project so Heroku knows to create a web dyno, that runs gunicorn and serves the Django app
  11. The final iteration of this app uses Amazon S3 for static and media storage, so the necessary changes needed to be made to settings.py for this as well

Important Extras

Heroku re-uploads the entirety of the static files to AWS with every commit, which causes the free tier limit to be reached within days. To avoid this, DISABLE_COLLECTSTATIC = 1 was added to Config Vars on Heroku. It is then necessary to manually run env USE_AWS='True' bash -c 'python3 manage.py collectstatic' locally to push the static file changes to production (used by Heroku).


This project additionally uses fixtures to populate initial data into some of the Django models. As these use a primary key of 0, the following needed to be run in Terminal before fixtures could be loaded:

ALTER SEQUENCE XX_TABLE_PKFIELD_SEQ_XX MINVALUE 0 START 1 RESTART 0

Then: python3 manage.py loaddata XX_FIXTURESFILE.yaml_XX as in Django docs

Credits

The base template was cloned from the Code Institute GitHub repository. Various other resources were used for different features. They are all listed below, categorised accordingly.

Site Content

Database Objects

*These will be replaced with actual in-stock products and details, once these are sourced

JSON Data

Sorting and Filtering

POST Requests

Miscellaneous Django/Python

Miscellaneous JavaScript

Miscellaneous CSS