Skip to content

Delphin Lifesaving Club is a Swimming and Lifesaving club based in Dublin. This e-shop allows swimmers (new and current) to purchase club apparel and swimming credits.

Notifications You must be signed in to change notification settings

rebeccatraceyt/delphin_lifesavingclub

Repository files navigation

Delphin Logo

The Delphin Lifesaving Club e-shop was designed, built and deployed by Rebecca Tracey-Timoney as the fourth and final Milestone Project to be completed for the duel Software Development Diploma from The Code Institute and UCD. The purpose of this online shop is to provide a virtual shopping environment for club members (future and current) to browse and purchase Delphin products, including classes and club apparel. The website provides a smooth and uncomplicated online shopping experience for users, with its simplistic and intuitive design.

View the live project here


Table of contents

  1. UX
    1. Project Goals
    2. User Stories
    3. Development Planes
  2. Information Architecture
    1. Database
    2. Data Models
  3. Features
    1. Design Features
    2. Existing Features
    3. Features to Implement in the future
  4. Issues and Bugs
  5. Technologies Used
  6. Testing ☞ Testing.md
  7. Deployment
  8. Credits
  9. Acknowledgements

Delphin Responsivness Example

UX

Project Goals

User Goals

The User is looking to:

  • Securely purchase available Club course credits
  • Securely purchase club apparel
  • Contact the Delphin Team
  • Learn about the club (for prospective members)
  • Navigate through the online store with ease

Developer / Site Owner Goals

The Developer is looking to:

  • Provide and professional and trustworthy webshop, helping users to meet their goals.
  • Reach a wider audience of prospective members through online intergration, making it easier to get involved.
  • Provide a seamless process, allowing swimmers to pre-purchase lesson credits, prior to registration, avoiding unnecessary waiting times on location.
  • Showcase the variety of lessons that Delphin provides.
  • Showcase the Club's apparel collection
  • Demonstrate their proficiency in a variety of software development skills, using newly learned languages and libraries as well as a document database system.
  • Deploy a project they are proud of, and excited to have, on their portfolio.

User Stories

As a user, I want to:

  1. View all products, to purchase my desired items.
  2. Filter through categories, to only see relevant products.
  3. Use a search query, to find a specific product or product type.
  4. Add items to my shopping bag, to begin the order process.
  5. Receive visual feedback that my item has been added to the bag, to confirm my selection.
  6. Select a course on a specific day, to suit my needs.
  7. Select apparel in a specific size, to suit my needs.
  8. View contact information for the club, to communicate with team.
  9. Connect with the club on one of their social apps, to communicate with the team.
  10. Get a breakdown of classes offered, to find one that suits my needs.
  11. Navigate to a page that could help me with my enquiry, to answer my question.

As a new visitor, I want to:

  1. Create an account, to unlock registered user features.

As a returning visitor, I want to:

  1. Easily log into my existing account, to unlock registered user features.
  2. View my previous orders, to keep a record of my transaction.
  3. Save default information, to save time for future orders.
  4. Edit default information, to update any necessary fields.
  5. View shopping bag to get an overview of products I wish to order.
  6. Remove products from my bag, to suit my needs.
  7. Update a product's quantity, to suit my needs.
  8. Get real-time feedback on available stock, to make purchase decisions.
  9. Proceed to a secure checkout, to make a purchase.
  10. Have clear visual feedback of the order process, to understand all steps of the process.
  11. Be able to edit my bag at all times, to allow change of mind.
  12. Receive a summary of my order via email to confirm that my transaction has been process.

Development Planes

In order to design and create the application, the developer distinguished the required functionality of the site and how it would answer the user stories, as described above, using the Five Development Planes:

1. Strategy

Broken into three categories, the website will focus on the following target audiences:

  • Roles:

    • New Swimmers
    • Current Swimmers
    • Parents/Guardians of Swimmers
  • Demographic:

    • Aged 16+ (to make a purchase)
    • Dublin (or neighbouring counties) resident
    • Active/Sporty
    • Swimming/Lifesaving Orientated
  • Psychographics:

    • Personality & Attitudes:
      • Sporty
      • Outgoing
      • Team Orientated
    • Values:
      • Friendship
      • Community
      • Activeness
    • Lifestyles:
      • Sporty
      • Team Player
      • Outgoing

The website needs to enable the user to:

  • Create an account or log in to an existing one
  • Purchase a course
  • Purchase Club Apparel
  • View past purchases
  • Edit/Save Delivery Information
  • Find out more about the club:
    • Academy Programme
    • General Questions
  • Get in contact:
    • WhatsApp
    • Facebook
    • Email(mailto)
    • Phone
    • Contact Form

The website needs to enable the client to:

  • Display all available course
  • Provide a virtual shop for Club Apparel
  • Provide club information:
    • Academy Programme
    • General Questions
  • Provide a point of contact:
    • WhatsApp
    • Facebook
    • Email(mailto)
    • Phone
    • Contact Form

With these goals in mind, a strategy table was created to determine the trade-off between importance and viability with the following results:

Delphin Opportunity Matrix

2. Scope

A scope was defined to identify what needed to be done in order to align features with the strategy previously defined. This was broken into two categories:

  • Content Requirements

    • The user will be looking for:
      • Product Information:
        • Name
        • Description
        • Image
        • Size (where applicable)
        • Day (where applicable)
      • Contact Information:
        • WhatsApp
        • Facebook
        • Email(mailto)
        • Phone Number
        • Contact Form
      • Academy Programme
      • General Questions
      • Create/Login to Profile
        • Save default information
        • View Previous Orders
      • Thematic Imagery and Typography
        • Club logo and colours
        • Typography matching club aesthetic
  • Functionality Requirements

    • The user will be able to:
      • Search Products
        • Courses:
          • By Age
        • Apparel
          • By Type
      • Make Transactions
      • Sign Up / Login to profile
        • Edit Profile information
        • View Previous orders
        • View shopping bag
      • Interact with shopping bag
        • Add to bag
        • Review bag contents
        • Update bag contents (increase quantity)
        • Remove from bag
      • Read the Academy Programme
      • Find answers to frequent questions

3. Structure

The website's navigation was organized in order to ensure that users could navigate through the site with ease and efficiency, with the following results:

Navigation Structure for User Management: User Management Information Architecture
Navigation Structure for Product Management: Product Management Information Architecture
Navigation Structure for Transaction Management: Transaction Management Information Architecture

4. Skeleton

Wireframe mockups were created in a Figma Workspace with providing a positive user experience in mind:

Home Page Wireframe
All Products Page Wireframe
Search Page Wireframe
Individual Product Page Wireframe
Add Product Wireframe
Login Page Wireframe
Register Page Wireframe
Club Ethos Page Wireframe
Academy Programme Page Wireframe
Contact Page Wireframe
Shopping Bag Page Wireframe
Checkout Page Wireframe
Order Summary Page Wireframe
User Profile Page Wireframe

Post Mock-Up Design Changes While the developer relied heavily on these Wireframes in order to maintain the desired design, there are several differences between the Mockups and the final product:

  • Primarily, the majority of the page content was changed to better suit the club and the information it wanted to display.
  • The addtion of an Order Review page was needed in order to provide a better user checkout story.
  • The All Product page filters were necessarily divided into Apparel and Courses page. The initial design was to have one page for all products but this became too messy for UI reasons.
  • The Profile page was split into two pages for a better user experience. Dividing the information update section and the order history provided a much needed and less 'busier' experience.
  • As stated in the TESTING file, earlier testing stages altered the category buttons on the Home, Shopping Bag and Search pages, providing a wider variety of categories for the user to better refine their search.

5. Surface

  • Colour Scheme

    • The chosen colour scheme was specifically selected to match the club colours. They are representitive of Lifesaving equipment used, such as flags and lifebuoys.

    • The red colour is specific to Lifeguarding and is used to highlight anything Lifeguarding related.

    • The Blus is an accent colour used in the club logo and beyond for colour contrast.

Delphin Colour Palette
  • Typography

    • The primary font chosen is Lato. A humanist sans-serif typeface, Lato is semi-rounded with a structured, but friendly warmth.

      Lato Typography Example

    • The Secondary font (accent font) chosen is Londrina Solid. A newfolk typeface, with a rough, handwritten feel, for versatile screen display.

      Londrina Typography Example

    • The secondary font is an updated version of the font used in the club's typography for logo and official letters. The font is paired well with the primary font, in order provide a minimally contrasting font combination serving as a practical and professional typeface with a hint of playfulness. This highlights the club's character for being professional, yet friendly, setting the tone for new and unfamiliar vistiors.

  • Imagery

    • The imagery used was created by the developer using the application Procreate in order to create a consistency of the elements while maintaining the look and feel of the application.

    • The product imagery used digital renderings and, where permitted, the developer edited them to display the Club imagery and colour scheme. A complete list of credits can be found in a separate file here.

Back to top ⇧


Information Architecture

Database

  • During development, a single-database was setup using SQLite as this is included and did not require any further installation to support.
  • Upon deployment, Heroku Postgres was used, as this is an add-on service provided by Heroku.

Data Models

Lato Typography

model diagram created using DrawSQL

A full list of the data models used on the site are below:

User Model

Name Database Key Field Type Type Validation
User user OneToOneField(User) on_delete=models.CASCADE
Full Name default_full_name Charfield max_length=50,
null=True,
blank=True
Phone Number default_phone_number Charfield max_length=20,
null=True,
blank=True
Street Address 1 default_street_address1 Charfield max_length=80,
null=True,
blank=True
Street Address 2 default_street_address2 Charfield max_length=80,
null=True,
blank=True
Town Or City default_town_or_city Charfield max_length=40,
null=True,
blank=True
County default_county Charfield max_length=80,
null=True,
blank=True
Postcode default_postcode Charfield max_length=20,
null=True,
blank=True
Country default_country CountryField blank_label='Country',
null=True,
blank=True

Users App

A custom User model was created using Django AllAuth to ensure secure functionalty of user registration and authentication.

UserProfile Model
Name Database Key Field Type Type Validation
User user OneToOneField(User) on_delete=models.CASCADE
Full Name default_full_name Charfield max_length=50,
null=True,
blank=True
Phone Number default_phone_number Charfield max_length=20,
null=True,
blank=True
Street Address 1 default_street_address1 Charfield max_length=80,
null=True,
blank=True
Street Address 2 default_street_address2 Charfield max_length=80,
null=True,
blank=True
Town Or City default_town_or_city Charfield max_length=40,
null=True,
blank=True
County default_county Charfield max_length=80,
null=True,
blank=True
Postcode default_postcode Charfield max_length=20,
null=True,
blank=True
Country default_country CountryField blank_label='Country',
null=True,
blank=True

Shop App

Category Model
Name Database Key Field Type Type Validation
Programmable Name name charfield max_length=254
Friendly Name friendly_name Charfield max_length=254
ProductOption Model
Name Database Key Field Type Type Validation
Programmable Name product_option charfield max_length=255
Friendly Name option_name Charfield max_length=255,
default='Monday'
Product Model
Name Database Key Field Type Type Validation
Product Name name charfield max_length=254
Description description Textfield default='test'
Price price Decimalfield max_digits=6,
decimal_places=2
Category category ForeignKey(Category) null=True,
blank=True,
on_delete=models.SET_NULL
Product Select product_select ManyToManyField(ProductOption) through='ProductSelect',
related_name='product_options',
blank=True
Course Check is_course Boolean default=False,
null=True,
blank=True
Apparel Check is_apparel Boolean default=False,
null=True,
blank=True
Course Information course_info TestField default='Test',
null=True,
blank=True
Course Age Range course_age CharField max_length=255,
default='10 years'
Image image Imagefield null=True,
blank=True

(course_info and course_age were used to create unique modals for each course page, providing users with further information on each course, avoidin page over-crowding or unecessary linking to other pages.)

ProductSelect Model
Name Database Key Field Type Type Validation
Selected Product Option product_select ForeignKey(ProductOption) on_delete=models.CASCADE
Selected Product product ForeignKey(Product) on_delete=models.CASCADE,
related_name='product_options'
Stock Count stock_count IntegerField default=30

Checkout App

Order Model
Name Database Key Field Type Type Validation
Order Number order_number Charfield max_length=32,
null=False,
editable=False
User user_profile ForeignKey(User) null=True,
blank=True,
on_delete=models.SET_NULL,
r elated='orders'
Full Name full_name Charfield max_length=50,
null=False,
blank=False
Email Address email EmailField max_length=254,
null=False,
blank=False
Phone Number phone_number Charfield max_length=20,
null=False,
blank=False
Street Address 1 street_address1 Charfield max_length=80,
null=False,
blank=False
Street Address 2 street_address2 Charfield max_length=80,
null=True,
blank=True
Town Or City town_or_city Charfield max_length=40,
null=False,
blank=False
County county Charfield max_length=80,
null=False,
blank=False
Postcode postcode Charfield max_length=20,
null=False,
blank=False
Country country CountryField blank_label='Country*',
null=False,
blank=False
Order Date date DateField auto_now_add=True
Delivery Cost delivery_cost DecimalField max_digits=6,
decimal_places=2,
null=False,
default=0
Order Total order_total DecimalField max_digits=10,
decimal_places=2,
null=False,
default=0
Grand Total grand_total DecimalField max_digits=10,
decimal_places=2,
null=False,
default=0
Original Bag original_bag TextField null=False,
blank=False,
default=''
Stripe Payment Intent ID stripe_pid CharField max_length=254,
null=False,
blank=False,
default=''
OrderLineItem Model
Name Database Key Field Type Type Validation
Order order ForeignKey(Order) null=False,
blank=False,
on_delete=models.CASCADE,
related_name='lineitems'
Product product ForeignKey(Product) null=False,
blank=False,
on_delete=models.CASCADE
Selected Product Option product_select charfield max_length=10,
null=False,
blank=False
Quantity quantity IntegerField null=False,
blank=False,
default=0
Lineitem Total lineitem_total DecimalField max_digits=6,
decimal_places=2,
null=False,
blank=False,
editable=False

Pages App

SwimCategory Model
Name Database Key Field Type Type Validation
Programmable Name name charfield max_length=254
Friendly Name friendly_name Charfield max_length=254
SwimProgramme Model
Name Database Key Field Type Type Validation
Programme Name name charfield max_length=254
Description description Textfield
Age Range age charfield max_length=254
Swim Category swim_category ForeignKey(SwimCategory) null=True,
blank=True,
on_delete=models.SET_NULL
FAQ Model
Name Database Key Field Type Type Validation
Question question charfield max_length=254
Answer answer TextField

Back to top ⇧


Features

Design Features

Each page of the websire features a consistently responsive and intuitive naviational system:

Navbar

  • A navbar is conventionally placed on the top of each page, excluding the checkout pages, containing easily identifiable and accessible navigational links with the club logo that redirects users to the home page.
  • The navbar utilises dropdown menus to provide a clean design, with each link appropriately categorised.
  • An active class provides feedback to users on their current location, through distinguishable differences on active links and their respective category title.
  • If the user is in session, an additional dropdown menu provides users with account functionality.
  • On mobile and tablet devices, the navigation menu collapses into a conventionally positioned hamburger menu, with all navigation links inside.
  • The shopping bag is centrally placed on mobile and tablet devices for quick and convenient access to the user's bag.
  • Toasts are displayed under the navbar, providing users with real-time feedback on their actions.

Footer

  • The footer contains a convenient quick-links area for users to navigate to their preferred location with east
  • The links are divided into appropriate categories, allowing users to see the variety of pages the website has. Notably, they also provide a means to categories the Apparel and Courses available, allowing users to find their desired products quicker.
  • These links are displayed in three columns on larger devices, two columns and medium and single columns on small.
  • The footer also provides the Club social links and copyright information.
    • Link to Club Facebook page
    • Mailto link to club emails
    • Link to Clubs Whatsapp correspondence number

Page Layout

  • A banner title is provided on each page to help users to quickly determine their location

  • Jinja was used to extend the base.html page, allowing for the utmost consistency and preservation of functionality across all pages. The extended block elements created the same basic layout for each page:

    <nav>
         <!-- Navigational content -->
    </nav>
    
    {% block messages %}
         <!-- Appropriate toast messages -->
    {% endblock %}
    
    {% block content %}
         <!-- Content unique to each page -->
    {% endblock %}
    
    <footer>
         <!-- Footer content -->
    </footer>
    

Existing Features

General Pages:

Home Page

Feature Description
Hero Image The hero image depicts a pool, clearly defining the website's affiliation and purpose for users (for club interaction)
Club Statement and Logo The club statement and logo are overlayed on the hero image, introducing the club.
Duel Links Links are displayed to provide users quick-link access to product categories. Both images and buttons redirect users to their respective categories.

All Products Page

Feature Description
Breadcrumbs Page breadcrumbs allow users to backtrack to the Home page
Category Filters Category filters are in place to allow users to refine their search. On mobile and tablet devices this is in a dropdown menu, on larger devices buttons are used.
Product Links All products are displayed on this page, allowing users to select their preference. The product cards provide users with a link from the product image and name to the product details page.
Pagination Pagination displays 12 products per page, avoiding unneccary scrolling.

Apparel Page & Courses Page

Feature Description
Breadcrumbs Allows users to return to the All Products or Home page.
Sub-Category Filters Allows users to refine their search to a particular product type (e.g. Apparel type or Course age range)
Product Links The product cards provide users with a link from the product image and name to the product details page.
Course Information Modal Specific to the Courses page, an information modal is displayed on click (represented by an i icon), providing information on purchasing a course.

Search Page

Feature Description
Input field Allowing users to enter their search query, with an appended search button.
Category Buttons Category filters provide users with a convenient quick-link to the categories, in lieu of searching for something. Both images and buttons redirect users to their respective categories.
Category Filters Category filters are in place to allow users to refine their search, directing to their prefered product type page.
Dynamic feedback When a user enters a term, there is dynamic text that displays the number of results returned and their search term. If there are no results, conditional text explains this to the user.
Reset Button Clicking the Search title will reset the search bar.

Individual Product Page

Feature Description
Breadcrumbs Allows users to return the category page for that product (Apparel or Courses) or Home page.
Dropdown Select Menu Allows users to refine their product selection (sizes of Apparel and times for Courses). Information is provided for stock availabilty for all product selections.
Quantity An input with appending and prepending buttons allows users to alter their quantity selection. This feature is dynamically designed to become inactive if the quantity count is 1 or at the product's stock availabilty.
Back Button Returns users back to the shop page, for convenience.
Add to Bag button Allows users to add their selection to their shopping bag

Login Page

Feature Description
Input fields Allows users to enter their username, or email, and password
Radio button Allows users to chose to remember their login details for convenience (allauth functionality)
Reset Password link Redirecting users to reset their password (allauth functionality)
Register button call-to-action button directing users to signup page

Register Page

Feature Description
Input fields Allows users to enter their information to register an account
Signup button Allows users to create their account (allauth functionality)

Club Ethos Page

Feature Description
Call to action links Links directing users to external pages for clarity purposes. Opens page on new tab.

Academy Programme Page

Feature Description
Accordion An accordion is used for each individual class, with the class name and age range displayed. Clicking the level opens the card and displays information pertaining to that level.
Hide/Show Buttons A Hide All and Show All button are used to provide users with the capacity to open all cards or close all cards, for convienience.
Call to action links Links directing users to external pages open on new tab, while internal pages are redirect users.

FAQs Page

Feature Description
Accordion An accordion is used for each question, with the question displayed. Clicking the question opens the card and displays the answer.
Hide/Show Buttons A Hide All and Show All button are used to provide users with the capacity to open all cards or close all cards, for convienience.
Call to action links Internal links redirecting users to useful pages within the site.

Contact Page

Feature Description
Embeded Google Maps A Google maps embed was used to provide users with an interactive map, with the pin dropped on the pool location. (Map reference)
Phone Link An anchor link was used for the Membership Officers phone number to provide a convenient quick-link.
Mailto action Three emails are provided using the club email address, with the difference in the subject line to highlight the message for the appropriate officer (for convienience) in order to help the user to send the message quicker.
Contact Form Used for users to conveniently send a message to our Marketing team. Validated using jQuery Validation.

Authorised User Pages:

Shopping Bag Page

Feature Description
Breadcrumbs Page breadcrumbs allow users to backtrack to the Home page
Duel Links Links are displayed when user's shopping bag is empty to provide quick-link access to product categories. Both images and buttons redirect users to their respective categories.
Keep Shopping button Link redirects users to the All Products page. Available when at all stages (when bag is both empty and containing items.
Remove button Placed at the top right of each product, allowing users to quickly remove the product from the shopping bag.
Quantity An input with appending and prepending buttons allows users to alter their quantity selection. This feature is dynamically designed to become inactive if the quantity count is 1 or at the product's stock availabilty.
Update button Updates the bag with the users inputed quantity.
Checkout button Directs users to the first page of the checkout process.

Order Review Page

Feature Description
No navbar or footer This conventionally removed, to minimalist checkout interface , preventing users from breaking the checkout process. (Source)
Logo Link Logo at the top of the page redirects users to the shopping bag for convienience
Heads-up display This shows the users the steps in the checkout process, giving them feedback on where they are and where they are going.
Return buttton Redirects users back to their shopping bag for editing.
Checkout button Directs users to the next page of the checkout process.

Order Details Page

Feature Description
No navbar or footer This conventionally removed, to minimalist checkout interface , preventing users from breaking the checkout process. (Source)
Heads-up display This shows the users the steps in the checkout process, giving them feedback on where they are and where they are going. Clicking the first number will return them to to the previous page
Input fields Allowing users enter their delivery information
Checkbox button Allowing users to chose to save their information to their profile
Order Summary Providing clear feedback on bag contents. On large screens, this is displayed on the right side of the screen. On mobile and tablet devices, this is displayed in a collapsable menu
Edit buttton Redirects users back to their shopping bag for editing.
Complete Order button Completes the checkout process.

Order Complete Page

Feature Description
Internal links Subtle links providing users with quick-link access to FAQs and Contact pages, for convienience.
Product Buttons Products ordered are displayed in a table (along with other order information, such as price and quantity) and act as buttons to the product detail page, for convienience.

User Profile Page

Feature Description
Call to action Buttons Displayed on the left side of the screen on larger devices and at the end of the page on mobile and tablet devices. Provide users with actions to take on their account, such as change password or emails, as well as logout and redirection to Past Orders page.
Input fields Allows users to add or edit their default information to provide them with a faster checkout experience.
Update button Saves new user information with toast used as feedback.

Past Orders Page

Feature Description
Call to action Buttons Displayed on the left side of the screen on larger devices and at the end of the page on mobile and tablet devices. Provide users with actions to take on their account, such as change password or emails, as well as logout and redirection to Profile page.
Call to action buttons User's order history is displayed on the right side of the screen on larger devices and at the top (single column) on smaller screens. It provides a snapshop of order information, including date of purchase, number of items, order total and a call-to-action View button allowing them to view the Order Complete page with appropriate conditional text to let them know this is a past order.

Features to Implement in the future

  • SwapShop Page

    • As children tend to grow out of their clothing quickly, a service we are looking into providing is a 'SwapShop' allowing swimmers to trade club gear (excluding swimwear) with others, passing it along to to others when they grow out of it.
    • The devloper looked into implementing this, researching how to set up a virtual noticeboard, but it proved to require a far greater skillset than their current abilities.
  • QR Codes

    • Another feature that was looked into was providing unique QR codes with every class purchase.
    • The club is currently looking into implementing this into their registration process, to avoid paperwork methods, and are only in the design stages.
    • The project time constraint was the deciding factor as the devloper needed to finish the design of the scanning process and learn how to implement it in order to use it.
  • Swimmer Profiles

    • As the club moves away from paperwork methods, integrating into a more technologically minded system (for GDPR reasons), we would want to expand this webshop into providing a 'Swimmer Profile', allowing swimmers to log in to see their progress week-by-week.
    • Although looked into, the current skillset discouraged the developer to research this feature any further as they did not think they could do it the justice the feature deserves.

Back to top ⇧


Issues and Bugs

The developer encountered a number of issues during the development of the website, with the noteworthy ones listed below, along with solutions or ideas to implement in the future.

Pagination
In implementing the pagination feature (allowing only 12 products to be displayed on the page at any given time), the developer encountered an issue wherby, when applying pagination on the filtered pages, All Apparel, All Courses and Search, the feature would reset the filters set (e.g. the product categories) from the second page, meaning, that instead of the refined search the user had selected, all products would be displayed. This was not practical and rendered the category filtering system useless, so the devloper had to omit the pagination on these pages. The work around was to provide category filtering buttons at the top of the page, so that the user did not have to scroll through all products, but could instead just display the sub-categories they desired.

Users App
The original design of the User model was called the Profile model. This was a fatal error on the developers part as it clashed with the integrated profile authorisation from allauth. As a result, the developer had to revert two commits and re-create the profile app as the new users app to restore functionality.

Google Maps Embed
The developers original design called for a Google Maps API to be used on the contacts page, giving users the ability to view the pool location with ease and clarity. On researching the methods of implementation, they discovered there were issues in using the API, the primary problem being authorisation when deploying on Heroku. From various sources, it was clear that additional variables were necessary in order to create a functioning map. It was decided, in order to avoid these additional steps, that an embedding of the map would be used instead. Sourced from Google Map Generator.

Quantity Counter
The biggest issue the developer faced was implementing the stock_count functionality. The feature was in the original designs, and the developer heavily researched how to create it, using ManyToMany relationships amongst their models. Through plenty of trial and error, and with the incredible patience of their mentor, the developer was able to achieve functionality. An issue arose in the implementation with a clash between the stock_count and quantity fields, where the user could select more than the product's current stock and put it in their bag. The developer was able to fix this by adapting a sourced solution from Stack Overflow.

Back to top ⇧


Technologies Used

Languages

Tools

  • Git
    • Git was used for version control to commit to Git and push to Heroku.
  • GitHub
    • GitHub was used to store the project repository, after pushing.
  • Heroku
    • Heroku was used in order to deploy the website.
  • Django
    • Django was used as the web framework for the application.
  • AWS
    • The Amazon Web Service s3 Bucket was used to store static and media files in the production database.
  • Stripe
    • Stripe was used to handle user payments on the webshop.
  • Figma
    • Figma was used to create the wireframes during the design phase of the project.
  • Am I Responsive?
    • Am I Responsive was used in order to validate the responsiveness of the design throughout the process, and to generate mockup imagery to be used.
  • Procreate
    • Procreate was used to create and edit images as well as using the colour picker tool to ensure consistency throughout.
  • Font Awesome
    • Font Awesome was used in conjunction with Iconify for icons used throughout the website.

Libraries

  • Bootstrap
    • Bootstrap was used to implement the responsiveness of the site, using bootstrap classes.
  • jQuery
    • jQuery was used to simplify the JavaScript code used.
  • Google Fonts
    • Google fonts was used to import the fonts "Indie Flower" and "Work Sans" into the style.css file. These fonts were used throughout the project.
  • jQuery Validation
    • jQuery Validation was used to simplify form validation for the Contact Form.
  • SweetAlert2
    • SweetAlert2 was used to customise the Contact Form success message for UX
  • Jinja
    • Jinja templating language was used to simplify and display backend data in html.

Database Management

  • SQLite
    • SQLite was used as a single-file database during development.
  • Heroku Postgres
    • Heroku Postgres was used for production database, provided by Heroku.

Main Packages

  • Django AllAuth
    • AllAuth was the primary method for user authentication, registration and account management.
  • Django Crispy Forms
    • Crispy Forms was used to style Django Forms.
  • Pillow
    • Pillow was used to aid in image processing on the database.
  • Django Countries
    • Django countries was used to ensure correct country codes were used in user forms.

Back to top ⇧


Testing

Testing information can be found in a separate testing file


Deployment

To further develop this project, a clone can be made using the following steps:

Deployment Instructions assume you are working on a MacOS and may differ on other operating systems. Please check documentation specific for your operating system

Prerequisites

To run the project on your own IDE, ensure you have the following:

Local Copy Creation

A Local Clone of the repository can be made in two ways:

1. Forking the Repository:

By forking the GitHub Repository we make a copy of the original repository on our GitHub account to view and/or make changes without affecting the original repository by using the following steps:

  1. Log into GitHub or create an account.
  2. Locate the GitHub Repository.
  3. At the top of the repository, on the right side of the page, select "Fork".
  4. You should now have a copy of the original repository in your GitHub account.

2. Creating a Clone:

How to run this project locally:

  1. Install the GitPod Browser Extension for Chrome.
  2. After installation, restart the browser.
  3. Log into GitHub or create an account.
  4. Locate the GitHub Repository.
  5. Click the green "GitPod" button in the top right corner of the repository. This will trigger a new gitPod workspace to be created from the code in github where you can work locally.

How to run this project within a local IDE, such as VSCode:

  1. Log into GitHub or create an account.

  2. Locate the GitHub Repository.

  3. Under the repository name, click "Clone or download".

  4. In the Clone with HTTPs section, copy the clone URL for the repository.

  5. In your local IDE open the terminal.

  6. Change the current working directory to the location where you want the cloned directory to be made.

  7. Type 'git clone', and then paste the URL you copied in Step 3.

    git clone https://github.com/USERNAME/REPOSITORY
    
  8. Press Enter. Your local clone will be created.

    (Further reading and troubleshooting on cloning a repository from GitHub here)

Local Deployment

Once a local clone is created, follow the below steps to deploy locally:

  1. Install all project requirments using the below command in the CLI terminal:

    pip3 install -r requirements.txt
    
  2. Create a .gitignore file in the project's root directory.

  3. Create an env.py file in the root directory.

  4. Add env.py to the .gitignore file.

  5. Within the env.py file, enter the project's environment variables:

    import os
    
    os.environ.setdefault("SECRET_KEY", <your_secret_key>)
    os.environ.setdefault("DEVELOPMENT", '1')
    os.environ.setdefault("STRIPE_PUBLIC_KEY", <your_key>)
    os.environ.setdefault("STRIPE_SECRET_KEY", <your_key>)
    os.environ.setdefault("STRIPE_WH_SECRET", <your_key>)
    
    • A secret key can be generated using Django Secret Key Generator*

    • Stripe Public and Secret keys can be generated after Stripe account signup. Keys are found in 'Developers' Section, under 'API Keys'

    • Webhook key (WH) can be generated under 'Developers' section of your stripe Dashboard. Select 'Add endpoint' and enter:*

    https://<yourhosturl>/checkout/wh/
    
    • Select 'Receive All Events' and 'Add Endpoint' and view your 'signing secret'
  6. Migrations will need to be made to create the local database and can be done using the following commands in the CLI terminal:

    python3 manage.py makemigrations
    
    python3 manage.py migrate
    
  7. Next, you will need to import the fixtures folders found in the Pages and Shop apps. The JSON files contain all data needed to host the database and can be imported using the following commands in the CLI terminal:

    python3 manage.py loaddata swim_category
    
    python3 manage.py loaddata swim_programme
    
    python3 manage.py loaddata faq
    
    python3 manage.py loaddata category
    
    python3 manage.py loaddata product
    
    python3 manage.py loaddata product_option
    
    python3 manage.py loaddata product_select
    
    • Ensure you import them in the correct order (as above), ensuring that the ManyToMany table is imported last, to avoid errors.
  8. A superuser will needed to be created to gain access to the Django Admin Page and can be created using the following commands in the CLI terminal:

    python3 manage.py createsuperuser
    
  9. Launch the project server using the below command in the CLI terminal:

    python3 manage.py runserver
    
  10. A server should be running locally on http://127.0.0.1:8000/. In running the server, a new SQLite3 database file (db.sqlite3) will be created in the root directory.

Once this is complete, the project should run within your local development environment.

Heroku App Creation

The website requires back-end technology, including a server, application and database. It is because of this that the project was deployed on Heroku, a container-based cloud Platform as a Service. There are two ways to deploy on Heroku:

  • Using the Heroku Command Line Interface
  • Connect to GitHub Repository (the developer recommends this method)

Create Heroku App

  1. Log into Heroku or create an account.
  2. Select the New button on the top-right of the page, and choose Create New App. Give your app a unique name (something that is the same, or similar to, your Django App) and set the region (in this instance: Europe). Then click Create App.
  3. Navigate to the Deploy tab on the dashboard and select Connect to GitHub.
  4. Search for the repository name (ensuring it is spelled correctly). Once located, click Connect.

Create PostgreSQL Database

  1. On the Heroku dashboard, navigate to Resources section.
  2. In the search bar, enter postgres and select Heroku Postgres.
  3. For this project, the plan name os Hobby Dev - Free, but feel free to select your own.
  4. Once a plan is selected, Submit Order Form.

Configure Heroku Variables

  1. On the Heroku dashboard, navigate to Settings and locate Reveal Config Vars button to set the following necessary variables for the project (Note: You may not have all variable values yet, add the ones that you have available and add the others in due course):

    Key Value
    AWS_ACCESS_KEY_ID Your AWS Access Key
    AWS_SECRET_ACCESS_KEY Your AWS Secret Access Key
    DATABASE_URL Your Database URL
    EMAIL_HOST_PASS Your Email Password
    EMAIL_HOST_USER Your Email Address
    SECRET_KEY Your Secret Key
    STRIPE_PUBLIC_KEY Your Stripe Public Key
    STRIPE_SECRET_KEY Your Stripe Secret Key
    STRIPE_WH_SECRET Your Stripe WH Key
    USE_AWS TRUE
    Ensure all values are the same as the values set in your env.py file
  2. Navigate back to the Deploy tab and scroll down to Automatic Deploys.

  3. Ensure that the master branch is selected, then select Enable Automatic Deploys.

Configure PostgreSQL Database

  1. In the project CLI, install the following dependancies to use Postgres:
    pip3 install dj_database_url
    
    pip3 install psycopg2_binary
    
    pip3 install gunicorn
    
  2. Freeze new dependancies using $ pip3 freeze > requirements.txt
  3. Create a Procfile file so that Heroku knows which file runs the app. In the terminal window, type the following command:
    $ echo web: python app.py > Procfile
    
    Remove the blank line that may occur at the end of the Procfile to avoid any issues
  4. Push the two files to the repository:
    $ git add .
    $ git commit -m "Commit Message"
    $ git push
    
  5. In the project's settings.py file:
    • Add import dj_database_url to imports section (top)
    • Locate DATABASES constant variable within the file and replace it with the following:
      if "DATABASE_URL" in os.environ:
           DATABASES = {"default": dj_database_url.parse(os.environ ["DATABASE_URL"])}
      else:
           DATABASES = {
           "default": {
                "ENGINE": "django.db.backends.sqlite3",
                "NAME": BASE_DIR / "db.sqlite3",
           }
      }
      
      
  6. Backup current SQLite database by entering the following into the CLI:
    ./manage.py dumpdata --exclude auth.permission --exclude contenttypes > db.json
    
  7. Login into your Heroku CLI using:
    heroku login -i
    
  8. Migrate models to the new Postgres database:
    python manage.py makemigrations
    
    python manage.py migrate
    
  9. A new superuser will needed to be created to gain access to the Django Admin Page and can be created using the following commands in the CLI terminal:
    python3 manage.py createsuperuser
    
  10. Reload the data into the new database using the folowing:
    ./manage.py loaddata db.json
    
  11. Temporarily disable COLLECTSTATIC to prevent Heroku from collecting static files until they have been set up on AWS:
    heroku config:set DISABLE_COLLECTSTATIC=1 --app <your app name>
    
    --app command is necessary if you have more than one heroku apps
  12. Add Heroku to the ALLOWED HOSTS varible in settings.py:
    ALLOWED_HOSTS = ['127.0.0.1',
                     '<your app name>.herokuapp.com',
                     'localhost']
    
  13. Push these changes to Github:
    $ git add .
    $ git commit -m "Commit Message"
    $ git push
    
  14. Set up push to Heroku:
    heroku git:remote -a <your app name>
    
  15. Push to Heroku:
    git push heroku main
    

Heroku will receive the pushed code from the GitHub repository and host the application with the required packages set out.

The deployed version can now be viewed by selecting View App in the top-right of the page.

AWS S3 Bucket Creation

All Static and Media files in the production version of this site are hosted on an Amazon Web Services(AWS) S3 Bucket.

To create your own bucket,

  1. Log into Amazon AWS or create an account.

Create AWS S3 Bucket

  1. Navigate to the S3 Bucket and create a unique bucket for your application using the Create Bucket button:
    • Give your bucket a name (same or similar to Django and Heroku app names)
    • Select the region closest to you
    • Uncheck Block Public Access and tick to acknowledge that the bucket will be public
    • Click Create Bucket
  2. On your Bucket Dashboard, locate the Properities section and configure the following:
    • Turn on Static Web Hosting
    • In index and errror, enter index.html and error.html
    • Click Save
  3. On your Bucket Dashboard, locate the Permissions section and configure the following:
    • In CORS:
    [
         {
              "AllowedHeaders": [
                   "Authorization"
              ],
              "AllowedMethods": [
                   "GET"
              ],
              "AllowedOrigins": [
                   "*"
              ],
              "ExposeHeaders": []
         }
    ]
    
    
    • In Bucket Policy, click Generate Policy and follow the below steps:
      • Click Policy > S3 Bucket Policy
      • Add * to the Principal Field (selects all principals)
      • Set Action to Get Object
      • Paste in ARN from previous page
      • Click Add Statement
      • Click Generate Policy
      • Copy and paste new policy into Bucket Policy
      • Add */ to the end of the Resources Key
      • Click Save
    • In Access Control List set the List Objects Permission to everyone
  4. Access IAM Dashboard from Sevices dropdown list
    • Create an new user group
    • Create a policy from the Policy tab
      • Select Import Managed Policy
      • Select S3 Full Access Policy
    • To override any existing content, in the Resource section, paste the following:
      [
           arn:aws:s3:::<your-bucket-name>",
           "arn:aws:s3:::<your-bucket-name>/*"
      ]
      
    • Continue to Create Policy
    • Attach new policy to the user group by locating the group and selecting Attach Policy next to your new policy.
    • Navigate to Users tab and select Add User Create a name and ensure it has Programmatic access. Add new user to the group.
    • Once the user is added, a .csv file will be provided.
      • Download this file and save these variables
      • Add variables to your Heroku Config Variables.
  5. Navigate to your Bucket and manually input all files in the media folder. For further information on creating a bucket, head to the AWS Instructions page

Configure Bucket

  1. In the project CLI, install the following dependancies to use AWS:
    pip3 install boto3
    
    pip3 install django-storages
    
  2. Freeze new dependancies using $ pip3 freeze > requirements.txt
  3. In the project's settings.py file, add storages to INSTALLED_APPS variable.
  4. In order to link your new AWS Bucket to your project, paste:
    if 'USE_AWS' in os.environ:
         # Cache control
         AWS_S3_OBJECT_PARAMETERS = {
              'Expires': 'Thu, 31 Dec 2099 20:00:00 GMT',
              'CacheControl': 'max-age=94608000',
         }
    
         # Bucket Config
         AWS_STORAGE_BUCKET_NAME = 'your_bucket_name'
         AWS_S3_REGION_NAME = 'your_region'
         AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
         AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
         AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
    
         # Static and media files
         STATICFILES_STORAGE = 'custom_storages.StaticStorage'
         STATICFILES_LOCATION = 'static'
         DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'
         MEDIAFILES_LOCATION = 'media'
    
         # Override static and media URLs in production
         STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{STATICFILES_LOCATION}/'
         MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{MEDIAFILES_LOCATION}/'
    
  5. Create a custom_storages.py file in your project's root directory. Inside it, include the Static and Media Storage locations:
    from django.conf import settings
    from storages.backends.s3boto3 import S3Boto3Storage
    
    class StaticStorage(S3Boto3Storage):
    location = settings.STATICFILES_LOCATION
    
    class MediaStorage(S3Boto3Storage):
    location = settings.MEDIAFILES_LOCATION
    
  6. Delete DISABLE_COLLECTSTATIC variable from your Heroku Config Variables
  7. Push these changes to Github:
    $ git add .
    $ git commit -m "Commit Message"
    $ git push
    

🎊 Congratulations! 🎊

Your project is ready to use. Have fun!

Back to top ⇧


Credits

The developer consulted multiple sites in order to better understand the code they needed to implement their deisgn.

The Code Institute Boutique Ado Mini Project was used as a reference point for the developer in the development of the core functionality of the website. The lessons included with the mini-project helped the developer to get a better understanding of each functionality and how to customise it to suit their project.

For code that was copied and edited, the developer made sure to reference this within the code. The following sites were used on a more regular basis:

Back to top ⇧


Acknowledgements

The developer would like to thank the following:

  • Their family and friends for the unrelenting support and encouragement they provided, most notably their very honest opinions during the testing phase.
  • The Slack community for the support and inspiration they gave.
  • Their mentor Seun for her patience and guidance throughout the process.

Back to top ⇧


About

Delphin Lifesaving Club is a Swimming and Lifesaving club based in Dublin. This e-shop allows swimmers (new and current) to purchase club apparel and swimming credits.

Resources

Stars

Watchers

Forks