Git Fit is a fitness subscription application.
The user's goal is to join a fitness community and purchase exercise plans and merchandise.
The site owner's goal is to build an active community around the product based on subscription and individual payments models, and to sell: exercise plans, nutrition plans, nutrition products and exercise products
Must haves for this project:
Nice to have:
To see the site in action, visit Git Fit
Initially I wanted to name the project Fit Family, and create a more family oriented webapp, but I didn't like the colour palette and couldn't find suitable images. Leftovers from this are still present in the code, but it doesn't affect the webapp.
Not all User Stories have been completed. Basic shopping functionality has been completed, but user stories that are about the community side of the project have yet to be resolved.
Viewing and Navigation | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 1 | Shopper | View a list of products | Select some to purchase | Products | |
✔️ | 2 | Shopper | View individual product details | Identify the price, description, product rating, product image and available sizes | Product details | |
✔️ | 3 | Shopper | Quickly identify deals, clearance items and special offers | Take advantage of special savings on products I'd like to purchase | Deals | |
✔️ | 4 | Shopper | Easily view the total of my purchases at any time | Avoid spending too much | Cart | |
✔️ | 5 | Site User | Easily view the site on any device | Use the site whenever and wherever I'd like | See the Responsiveness of Pages section |
Registration and User Accounts | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 6 | Site User | Easily register for an account | Have a personal account and be able to view my profile | Register | |
✔️ | 7 | Site User | Easily login or logout | Access my personal account information | Login | |
✔️ | 8 | Site User | Easily recover my password in case I forget it | Recover access to my account | Recover | |
✔️ | 9 | Site User | Receive an email confirmation after registering | Verify that my account registration was successful | Registration | |
✔️ | 10 | Site User | Have a personalized user profile | View my personal order history and order confirmations, and save my payment information | Profile | |
❌ | 11 | Site User | Easily review products | Help my fellow fitness community members to find the right product |
Sorting and Searching | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 12 | Shopper | Sort the list of available products | Easily identify the best rated, best priced and categorically sorted products | Sort | |
✔️ | 13 | Shopper | Sort a specific category of product | Find the best-priced or best-rated product in a specific category, or sort the products in that category by name | Category | |
✔️ | 14 | Shopper | Sort multiple categories of products simultaneously | Find the best-priced or best-rated products across broad categories, such as "clothing" or "exercise equipment" | Multi Category | |
✔️ | 15 | Shopper | Search for a product by name or description | Find a specific product I'd like to purchase | Search | |
✔️ | 16 | Shopper | Easily see what I've searched for and the number of results | Quickly decide whether the product I want is available | Screenshot for user story 15 works here too |
Purchasing and Checkout | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 17 | Shopper | Easily select the quantity of a product when purchasing it | Ensure I don't accidentally select the wrong quantity | Screenshot user story 2 | |
✔️ | 18 | Shopper | View items in my cart to be purchased | Identify the total cost of my purchase and all items I will receive | Screenshot user story 4 | |
✔️ | 19 | Shopper | Adjust the quantity of individual items in my cart | Easily make changes to my purchase before checkout | Same as above | |
✔️ | 20 | Shopper | Easily enter my payment information | Check out quickly and with no hassle | Checkout | |
✔️ | 21 | Shopper | Feel my personal and payment information is safe and secure | Confidently provide the needed information to make a purchase | Same as above | |
✔️ | 22 | Shopper | View an order confirmation after checkout | Verify that I haven't made any mistakes | Confirmation | |
✔️ | 23 | Shopper | Receive an email confirmation after checkout | Keep the confirmation of what I've purchased for my records |
Community | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
❌ | 24 | Subscriber | Post updates about my progress | Update my fellow members on my successes | ||
❌ | 25 | Subscriber | Add and edit information on my profile pertaining to my fitness goals | Receive nutrition and exercise plans tailored to my fitness goals | ||
❌ | 26 | Subscriber | Easily find other subscribers | Feel part of a community and get motivated | ||
❌ | 27 | Subscriber | Easily see updates from other subscribers | Feel part of a community and get motivated | ||
❌ | 28 | Subscriber | Easily find information about the subscriptions available | Make an informed choice about my subscription | ||
❌ | 29 | Subscriber | Easily find workouts | Work on my fitness goal | ||
❌ | 30 | Subscriber | Easily find nutrition plans | Work on my fitness goal |
Admin and Store Management | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 31 | Store Owner/Admin | Easily login or logout | Access the admin interface of the webapp | Admin | |
✔️ | 32 | Store Owner/Admin | Add a product | Add new items to my store | Add Product | |
✔️ | 33 | Store Owner/Admin | Edit/update a product | Change product prices, descriptions, images and other product criteria | Edit Product | |
✔️ | 34 | Store Owner/Admin | Delete a product | Remove items that are no longer for sale | Delete Product | |
❌ | 35 | Store Owner/Admin | Add a subscription | Add new subscription options | ||
❌ | 36 | Store Owner/Admin | Edit/update a subscription | Change subscription prices, descriptions, linked workouts and nutrition | ||
❌ | 37 | Store Owner/Admin | Delete a subscription | Remove subscriptions that are no longer available | ||
✔️ | 38 | Store Owner/Admin | Add a workout | Add new workouts | Add Workout | |
✔️ | 39 | Store Owner/Admin | Edit/update a workout | Change workouts | Edit Workout | |
✔️ | 40 | Store Owner/Admin | Delete a workout | Remove workouts that are no longer promoted | Delete Workout | |
❌ | 41 | Store Owner/Admin | Add a nutrition plan | Add new nutrition plans | ||
❌ | 42 | Store Owner/Admin | Edit/update a nutrition plan | Change nutrition plan | ||
❌ | 43 | Store Owner/Admin | Delete a nutrition plan | Remove nutrition plans that are no longer promoted | ||
✔️ | 44 | Store Owner/Admin | Add subscription features to the home page | To entice visitors to subscribe | Add Feature | |
✔️ | 45 | Store Owner/Admin | Edit subscription features visible on the home page | To tweak the features and entice visitors to subscribe | Edit Feature | |
✔️ | 46 | Store Owner/Admin | Delete subscription features visible on the home page | To remove features that are no longer offered | Same as above | |
✔️ | 47 | Store Owner/Admin | Add shop alerts to the products page | To update the shop and make visitors aware of for example new deals | Add Shop Alert | |
✔️ | 48 | Store Owner/Admin | Edit shop alerts visible on the products page | To change shop alerts | Edit Shop Alert | |
✔️ | 49 | Store Owner/Admin | Delete shop alerts visible on the products page | To remove shop alerts that are no longer applicable | Same as above |
Viewing and Navigation - Workouts | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 50 | Registered User | View a list of workouts | Select workouts to do | Workouts | |
✔️ | 51 | Registered User | View individual workout details | Identify the description, rating, equipment needed and what the workout targets | Workout Details |
Sorting and Searching - Workouts | Done | User Story ID | As A/An | I Want To Be Able To... | So That I Can... | Screenshot |
---|---|---|---|---|---|---|
✔️ | 52 | Registered User | Sort the list of available workouts | Easily identify the best rated, categorically sorted workouts | Sort | |
✔️ | 53 | Registered User | Sort a specific category of workout | Find the best-rated workout in a specific category, or sort the workouts in that category by name | Category |
Jesse James Garret's 5 planes of UX design were used to design the site. I started off at the Strategy Plane:
The main goal for visitors is to find and join a fitness community they might like.
This means giving visitors a feeling about the kind of community they are joining.
Git Fit sets out to be no nonsense and active, aggressive almost. Git Fit is for goal-oriented people. For now it is just a shop, but by adding subscriptions, we can create a community, with exercise and nutrition plans and a way for subscribers to connect.
So the main page has to have a call to action in the form of a button to take you to subscriptions. We also need a hero image that exemplifies the image of Git Fit. Some brief text to indicate what subscribers gain access to would also be good.
We also indicate that there is a shop, workouts and account option by having options for these in the navbar.
The functional specifications of the site:
Content requirements:
All pages should have the same navigation bar and footer:
The Home Page
The Profile Page
The Community Page - not yet implemented
The Shop Page
The Workouts Page
The Nutrition Page - not yet implemented
The navigation bar will be added to the top of every page and will always remain visible. It contains a home link on the left side, a search bar for searching in the store in the middle, an icon containing the workout options, an icon containing the account options - register and login, and if you're logged in a link to your profile, and if you're a superuser, a link to add a product.
There is also a cart icon, which updates when you add items to your cart and which links to the cart page, from where you can do checkouts.
There are links to all pages on this navbar, though some links are only visible if the user has logged in. On the left will be the logo, which when clicked upon will take the visitor back to the home page.
The home page has a hero image, a call to action to register, a button to take you to the shop and features of subscriptions.
The shopping page has cards for the products. You can choose different categories of products, sort by price and category and rating and click on a product to get more information and add it to your cart.
The cart page keeps track of the items you've added to your cart, giving you a running total and the option to check out.
The checkout page allows you to fill in shipping details and a creditcard for payment.
The checkout success page contains a summary of your order and order details.
The profile page contains a form to fill in delivery details or show prefilled delivery details, and has links to the order history for registered users.
The workouts page has cards for different workouts. You can choose workouts by body part they target, equipment needed or specific muscle groups they target. You can click on a workout to get more information about it.
At the bottom of every page will be the same footer, containing the brand, icons of various payment methods and links to various social media sites.
We use icons from Font Awesome to add some visual interest but also visual cues to indicate functionality.
We use Bootstrap as a basis, but add our own style. Git Fit needs to look no-nonsense, active, almost aggressive. To create a bold, active, almost aggressive look we use a black, red and white color scheme, similar to Netflix.
The header font is also chosen to reflect this: a slab serif font that is bold and in your face.
Buttons have no rounded borders, to create a sleek design. Red is mainly used as an accent color, to draw attention to elements on the page.
Wireframes
These wireframes were used as a basis to design the actual webapp. However, sometimes the actual project deviates from the wireframes, because the endresult looked better or was more easily achieved than the wireframe.
The layout of the workouts section is very similar to the shop and product pages, just with some slight change in details.
The database design can be found here There are 11 models:
The Profiles model is linked to the allauth User model, but I don't know how this model is constructed.
These screenshots indicate the responsiveness of the pages on various screens. Pages that require a login are not included, as are checkout and checkout success, as these require adding items to the cart.
Tests for Readme.md:
Automated tests
There are some automated tests using Django's own testing capabilities.
python manage.py test --verbosity=2
Output:
test_get_cart (cart.tests.TestViews)
When browsing to /cart/ we get ... ok
test_blank_feature (home.tests.TestModels)
When a feature is created with no ... ok
test_max_length_name_feature (home.tests.TestModels)
When a feature is created with a header longer than ... ok
test_get_home (home.tests.TestViews)
When browsing to / we get a 200 code, ... ok
test_get_login (home.tests.TestViews)
When browsing to /accounts/login we ... ok
test_get_password_reset (home.tests.TestViews)
When browsing to /accounts/password/reset ... ok
test_get_signup (home.tests.TestViews)
When browsing to /accounts/signup we ... ok
test_all_blank_product_category (products.tests.TestModels)
When a category is created with no ... ok
test_blank_description_product (products.tests.TestModels)
When a product is created with no description, ... ok
test_blank_fields_product (products.tests.TestModels)
When a product is created, category, sku, ... ok
test_blank_name_product (products.tests.TestModels)
When a product is created with no name, ... ok
test_blank_price_product (products.tests.TestModels)
When a product is created with no price, ... ok
test_blank_shopalert (products.tests.TestModels)
When a shopalert is created with no ... ok
test_friendly_name_blank_product_category (products.tests.TestModels)
When a category is created, friendly name is blank ... ok
test_max_length_image_url_product (products.tests.TestModels)
When a product is created with an image_url ... ok
test_max_length_name_product (products.tests.TestModels)
When a product is created with a name ... ok
test_max_length_name_product_category (products.tests.TestModels)
When a category is created with a name longer than ... ok
test_max_length_name_shopalert (products.tests.TestModels)
When a shopalert is created with a name longer than ... ok
test_max_length_sku_product (products.tests.TestModels)
When a product is created with a sku ... ok
test_delete_category_of_product (products.tests.TestViews)
When a category is deleted for a product, ... ok
test_all_blank_bodypart (workouts.tests.TestModels)
When a bodypart is created with no ... ok
test_all_blank_equipment (workouts.tests.TestModels)
When a equipment is created with no ... ok
test_all_blank_target (workouts.tests.TestModels)
When a target is created with no ... ok
test_blank_description_workout (workouts.tests.TestModels)
When a workout is created with no description, ... ok
test_blank_fields_workout (workouts.tests.TestModels)
When a workout is created, bodypart, equipment, ... ok
test_blank_image_workout (workouts.tests.TestModels)
When a workout is created with no image, ... ok
test_blank_name_workout (workouts.tests.TestModels)
When a workout is created with no name, ... ok
test_delete_fields_of_workout (workouts.tests.TestModels)
When the bodypart, equipment and target objects are deleted for a workout, ... ok
test_friendly_name_blank_bodypart (workouts.tests.TestModels)
When a bodypart is created, friendly name is blank ... ok
test_friendly_name_blank_equipment (workouts.tests.TestModels)
When a equipment is created, friendly name is blank ... ok
test_friendly_name_blank_target (workouts.tests.TestModels)
When a target is created, friendly name is blank ... ok
test_max_length_name_bodypart (workouts.tests.TestModels)
When a bodypart is created with a name longer than ... ok
test_max_length_name_equipment (workouts.tests.TestModels)
When a equipment is created with a name longer than ... ok
test_max_length_name_target (workouts.tests.TestModels)
When a target is created with a name longer than ... ok
test_max_length_name_workout (workouts.tests.TestModels)
When a workout is created with a name ... ok
test_get_workouts (workouts.tests.TestViews)
When browsing to /workouts/ we get a 302 code, ... ok
coverage run --source='.' manage.py test
Name Stmts Miss CoverTOTAL 1141 468 59%
Manual tests The webapp has been tested with Google Chrome, Firefox and Microsoft Edge, and on a Huawei P smart+ 2019 Android smartphone and found to be working fine. Below are more elaborate tests:
Viewing and Navigation | Test | Expected | Passed |
---|---|---|---|
Browsing to the home page as an anonymous user | I see a call to action to sign up, as well as several features that signing up will get me | ✔️ | |
Browsing to the home page as a logged in user | I just see the hero image and the 'Buy' button | ✔️ | |
Clicking on the social media links as either an anonymous user or logged in user | A new tab opens going to that social media page | ✔️ | |
Clicking on the navbar brand as either an anonymous user or logged in user | I go back to the home page | ✔️ | |
Clicking on the 'Buy' button as either an anonymous user or logged in user | I go to the products page and see a list of products | ✔️ | |
Clicking on the 'Register' button as an anonymous user | I go to the register page and see a form to register for an account | ✔️ | |
Clicking on the 'Workouts' button as an anonymous user | I see options to either register or login, which take me to either a register or login page | ✔️ | |
Clicking on the 'Workouts' button as logged in user | I see links to view all workouts, including workouts sorted in different ways | ✔️ | |
Clicking on the links under the 'Workouts' button as logged in user | I go to the workouts page, and if I selected a particular sorting, the workouts are sorted that way | ✔️ | |
Clicking on a workout image as a logged in user | I see workout details | ✔️ | |
Clicking on the 'My Account' button as an anonymous user | I see options to either register or login, which take me to either a register or login page | ✔️ | |
Clicking on the 'My Account' button as a logged in user | I see options to go to my profile or to logout, which take me to either my profile page or logout page | ✔️ | |
Clicking on a product image as an anonymous or a logged in user | I see product details and the option to add a product to my cart | ✔️ | |
Clicking on the 'Special Offers/All Specials' link as an anonymous or a logged in user | I see a list of products that are on some kind of special offer | ✔️ | |
Clicking on the cart icon as an anonymous or a logged in user after I added products to my cart | I see a list of products in my cart, with subtotals, delivery costs and the order total. The cart icon itself also indicates my current order total | ✔️ |
Registration and User Accounts | Test | Expected | Passed |
---|---|---|---|
Registering for an account via either the Register button on the home screen or the Register link in 'My Account' | I can fill in a form, receive an email with a confirmation link, confirm my account and then I have an account | ✔️ | |
Opening the 'My Account' menu | I can either login to my account, or logout if I'm already logged in | ✔️ | |
Recover my password | I can use the 'Forgot Password' button on the login page, fill in my email and then receive a working link to recover my password | ✔️ | |
Register for an account | I can use the 'Forgot Password' button on the login page, fill in my email and then receive a working link to recover my password | ✔️ | |
Clicking on 'My Account/My Profile' as a logged in user after I made an order | I see a form where I can fill in personal details, which I can update. I also see my order history, with links to the order confirmations | ✔️ |
Sorting and Searching | Test | Expected | Passed |
---|---|---|---|
As either an anonymous user or logged in user, I click on the sorting menu on the products page | I can sort the list of products using the sort menu, sorting by price, category, rating or name | ✔️ | |
As either an anonymous user or logged in user, I choose a collection of product categories and click on the sorting menu on the products page | I can sort this subcollection of products using the sort menu, sorting by price, category, rating or name | ✔️ | |
As either an anonymous user or logged in user, I enter a search term in the search bar | I get a page with the term I searched for, a counter with how many products were found, and if there are any products, a list of these products | ✔️ | |
As a logged in user, I click on the sorting menu on the workouts page | I can sort the list of workouts using the sort menu, sorting by body part, equipment, target, rating or name | ✔️ |
Purchasing and Checkout | Test | Expected | Passed |
---|---|---|---|
As either an anonymous user or logged in user, I use the quantity selector functionality on the product details page | I can adjust the quantity and add the product and desired quantity to my cart | ✔️ | |
As either an anonymous user or logged in user, I click on the cart icon in the navbar | I can view the items in my cart, subtotals, delivery costs and my order total | ✔️ | |
As either an anonymous user or logged in user, I use the quantity selector or delete functionality in the cart | I can adjust the quantity of a product in my cart or delete the product from my cart | ✔️ | |
As either an anonymous user or logged in user, I click on the 'Checkout' button | I can fill in my delivery details and card details and then checkout | ✔️ | |
As either an anonymous user or logged in user, I click on the 'Complete Order' button | I am taken to a checkout confirmation page, with details for my order | ✔️ | |
As either an anonymous user or logged in user, I click on the 'Complete Order' button | I receive an email with confirmation of my order | ✔️ |
Admin and Store Management | Test | Expected | Passed |
---|---|---|---|
I log in using superuser credentials at https://code-institute-ms4.herokuapp.com/admin | I am taken to the admin portal, where I can see and edit elements of the webapp | ✔️ | |
In the admin portal I perform CRUD operations on a Product | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on a Product_Category | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on an Order | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on an Shop alert | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on a Feature | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on a Workout | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on a Body part | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on an Equipment | The CRUD operations are applied | ✔️ | |
In the admin portal I perform CRUD operations on a Target | The CRUD operations are applied | ✔️ | |
Logged in as a superuser, I click on 'My Account' | I see a link for 'Add Product' which allows me to add a product to the store | ✔️ | |
Logged in as a superuser, I go to the Products page | I see links on each product that allow me to edit the product | ✔️ | |
Logged in as a superuser, I go to the product details page for a product | I see a link that allows me to edit the product | ✔️ | |
Logged in as a superuser, I go to the Products page | I see links on each product that allow me to delete the product | ✔️ | |
Logged in as a superuser, I go to the product details page for a product | I see a link that allows me to delete the product | ✔️ | |
Logged in as a superuser, I click on 'Workouts' | I see a link for 'Add Workout' which allows me to add a workout to the site | ✔️ | |
Logged in as a superuser, I go to the Workouts page | I see links on each workout that allow me to edit the product | ✔️ | |
Logged in as a superuser, I go to the workout details page for a workout | I see a link that allows me to edit the product | ✔️ | |
Logged in as a superuser, I go to the Workouts page | I see links on each workout that allow me to delete the product | ✔️ | |
Logged in as a superuser, I go to the workout details page for a workout | I see a link that allows me to delete the product | ✔️ |
Code validation:
I tried fixing the stray
[Python Validation]
Run python3 -m flake8
and fix problems:
pip install -U autopep8
and ran it to fix many of the problems autopep8 --in-place --recursive .
pip install black
black .
One big bug was with the checkout process not working: after clicking on the checkout button, the loading spinner would appear, but would never progress to the checkout success page. To try and fix this bug I took the following steps:
Another bug I discovered was that updating the quantity in the cart didn't always work. Troubleshooting steps:
The only real problem was the implementation of Stripe. Getting this up and running took a lot of time, which meant I did not have time to implement other features. Right now, the project is a basic webshop, but not yet the community it sets out to be.
The project has been deployed to Heroku, with static files hosted on AWS S3. If you want to do the same:
If you want to run the project locally:
First, fork the repository to your own GitHub: https://github.com/RicardoAzuul/code-institute-ms4-fullstack.
Clone the forked repository to your own machine.
Install Python 3.8.12, as this is what the project was built with: https://www.python.org/downloads/release/python-3812/ (though if you're running Windows, install 3.8.10)
From the terminal, run the below to install required modules:
pip3 install -r requirements.txt
You will need to create an env.py file for running the app locally. The content of this file:
import os
os.environ.setdefault("SECRET_KEY", [django secret key]) os.environ.setdefault("DEVELOPMENT", "True") os.environ.setdefault("STRIPE_PUBLIC_KEY", "[stripe public key]") os.environ.setdefault("STRIPE_SECRET_KEY", "[stripe secret key]") os.environ.setdefault("STRIPE_WH_SECRET ", "[stripe webhook key]")
1. To run the app:
``` python manage.py startserver ```
1. This will run the app locally, you can then browse to http://192.168.1.68:5000/ to interact with the app.
---
## Credits
### Inspiration
The color scheme, black with accents of white and red, was inspired by Netflix: it looks bold. For the font I did some research into bold aggressive font types and came upon slab serif fonts. I picked Kelly Slab, as it was available via Google Fonts.
Initially I wanted to do something different and go for warm and friendly, but I did not like the color scheme and couldn't find suitable images.
### Content
Product images, prices, descriptions and ratings: www.decathon.nl
Workout information: from a dataset on Kaggle: https://www.kaggle.com/datasets/edoardoba/fitness-exercises-with-animations
The descriptions of workouts came from: https://www.bodybuilding.com/
### Media
Main page: https://www.pexels.com/photo/woman-doing-exercise-414029/
No image available file: https://commons.wikimedia.org/wiki/File:No_Image_Available.jpg
### Code
I've used some code from Bootstrap, as indicated by comments, and I found a nice way to do a back to top button that only appeared when scrolling down and slowly scrolls you back on Stackoverflow, as indicated by comments.
### Acknowledgements
- I received help and support from my mentor at Code Institute, [Jack Wachira](https://github.com/iamjackwachira).
- I would also like to thank to all the people at [Code Institute](https://codeinstitute.net/) for providing the Diploma in Software Development course and giving me the tools and guidance to create this app.
- I also received help from the Code Institute Slack Community when I had to resubmit my project, so thanks to the community as well.
- And also thanks to [Bootstrap](https://getbootstrap.com/) for helping with implementing their Bootstrap stylings, [Django](https://www.djangoproject.com/) for their documentation and [Stackoverflow](https://stackoverflow.com/) for helping with finding solutions to coding problems.
- My wife, Elizabeth Lane, for supporting me during this coding course.