SportsShooting is a site, which should support Sportsshooters and their related clubs, to create match events or gather information about matches. The main target audience are licensed IPSC (International Practical Shooting Confederation) shooters. IPSC is a worldwide organized confederation of practical shooters.
The site is not limited to licensed IPSC shooters, it can also be used for other shooting club related events.
It should build a plattform, where the registered user can gain more information about a particular match. He has, for example, the option to "attend" a match by clicking the related button, which will make it possible for other user, to see who is attending.
We as IPSC Shooters often attend matches and therefore travelling is essential. This app should help to find other IPSC shooters, who attend the same match and therefore can travel together. IPSC Matches are all classified within "Levels", which have a distinct meaning:
For this reason, the plattform provides predefined "Level" filters in order to navigate quicker.
A registered user will also have the possibility to comment on match listings and therefore get in contact with fellow colleagues.
If one is attending lots of matches, it can become difficult to track them, therefore the app shows all upcoming events, where a user has registered for. A dedicated Upcoming Popular Matches component is visibile on many occasions, displaying the most popular matches. It should support the shooter to attend them too.
The plattform also gives the IPSC Shooter the option to create his own and private gun collection site. There he can inventorise his collection.
Link to deployed SportsShooting site: SportsShooting
Link to the deployed backend Django API: SportsShooting API
Link to the backend Django API repository: SportsShooting API Repo
The overalll goal of the application was to achieve the desired functionality with a minimalistic and clear design. Colors should only be used to give an accent to something or display a certain function, like the buttons or the navbar active elements. Overall, the application is mobile friendly, the use of mobile devices has always been part of the design decision process.
Coolors.co has been used to create the color palette. There are two sets of color schemes used in the application, where as they have many similarities. The main application uses a mixture of white / grey colors, paired with red to give some accents. The main background is #f5f5f5
, which is a light grey color. It should give a simple accent over the pure white #ffffff
navbar and component background.
Since also the individual match and gun collection items use the pure white as background, scrolling over the elements gives a nice "floating" effect.
The navbar but mostly the buttons are using a mixture of red colors paired with either black or sort of grey. Two sorts of red are used, either the standard red #ff0000
or the #fff1f1
. Either the background or the font color is using one of them, also the hover effect is done with red. The background of the buttons is otherwise mostly the grey'ish #cfced3
paired with red or black font color.
I am aware of the fact that this combination does partially not fullfil the contrast check. However, it is almost impossible to pair red with any other light color and pass a contrast check. Since the whole color scheme is around the SportsShooting Logo, which contains a red centered target, I wanted to use it throughout the site. However, I am pretty confident that due to the fact that the contrast issue is only on a few button and hover effect occasion, it would also be very well usable for visual impaired users.
Google Fonts has been used to create the fonts. The logo uses the quite special Milonga
font, which gives a nice touch to the image of the logo.
The rest of the document uses Roboto
with a alternative font of sans-serif
.
The Wireframes are the prototype of this project and show the base idea and the skeleton of the app. They have been slightly adjusted during the development of the project but their main concept and design idea never changed. I've used Balsamiq to design my site wireframes.
This application, built with React has not a data model by itself, since it consumes API's from the back end. The whole code and documentation of the data model can be found in the corresponding DRF API repository: SportsShooting API Repo
This section will explain each feature of the application
The navbar is the heart of the whole application. It welcomes the user with a very clear and distinct design. The usage should be pretty clear by looking at it.
As a (new) user entering the page, it will be in unauthenticated state. The navbar displays the distinct logo, which is an active link where as clicking on it, will bring the user always back to the home url. furthermore, the user can see three icons
The matches icon appears red because it is active, it is the home url. This should give the user already a hint about the functionality. Hovering over the SignIn or SignUp icons will change their color, indicating that the user can click on it. Once clicked, the icon remains acive and hence turns color to red.
If a user is authenticated, the navbar looks slightly different but keeps the previously mentioned concept of functionality and design. The following additional icons will show up:
A user who wants to interract on the site and not just watch some content, needs to create a profile and therefore sign up. The SignUp icon on the navbar will bring him to the form, where he has to add minimal data. The form uses auto validation of the fields, meaning for example a too short password will display an error.
The image on the signup site shows some bullets, once in upward position. It should illustrate the purpose of this form, to "sign up". If someone has clicked on the sing up by accident but already has an account, there is a cross link to the sign in form.
The sign in form welcomes the user with the sentence "Are you ready". This is taken from the IPSC rules, which we follow as part of our sport. It is basically one of the commands the shooter gets told, before he can start his run on a particular stage. The image should illustrate the ready condition as well, the bullet comes from the magazine and gets loaded into the barrel.
Once the user is signed in, the sign out icon is always visible in the navbar.
The matches site is the main and home view of the application. It consists of different reusable components, which will show up independently on other sites.
The following elemets are part of the matches main site:
All of theses elements are available to all users, independet of their sign in status. The matches list is sorted showing the last added match first. This will help users to see the latest additions quite easily, without searching a lot. Furthermore, the list will also contain matches from the past, since this part of the application should also act as kind of archive.
There is an infinite scroll of matches in place, while loading from the back end, a loading spinner will be dispalyed to the user.
The search bar on top of the matches site give the user the ability to search after the most common keywords like title, location, advertiser
There is also a pre defined Level Filter in place. As explained in the introduction section of this application, in IPSC shooting, all matches are categorised into levels, each of them having a clear meaning.
The two features can be combined to further filter down possible matches. This is exactly what a shooter who is looking after matches, wants. Search and Level filter will give this option.
Besides match detail information, each match is also displaying the two active elements of attending with its attendings count as well as the comment and comments count
If a user is logged in, he can click the attend icon to add himself to the list of attending shooters. If so, the icon will be transformed to red and keep this color until the logged in user clicks again on it to unattend.
It is important to note, that also the user who added the match can attend his own match. This is a must have feature. The count displays how many shooters are attending. Furthermore, he can click on the comments icon, which brings him to the match detail site, where he can see and add a comment. The count displays how many comments have been written.
If a user is not logged in, he can see both components, however, he will not be able to attend a match. While trying to attend, a message will be displayed that only logged in users can use this feature.
Clicking on the comments field will also bring this user to the match detail site, where he can read the comments but is unable to add a comment.
The Upcoming popular Matches component is a dedicated separated component, visible on the matches site. It contains a list of the most popular matches, measured on how many shooters are attending. To keep the list kind of visible, it is limited to 5 entries on desktop and 4 entries on mobile.
The list only contains matches hapening in the future, popular matches from past are filtered out. Furthermore it is sorted by the most recent match being first in the list. If the user is hovering over the events, the will change the color to red, to show it is an active link. With this, the navigation is inline with the rest of the site. Clicking on such a link will bring the user to the match detail page.
Once the user clicks on an individual match in the matches list, or he clicks on one of the listed matches in the Upcoming Popular Matches component, he will be presented with the details of the particular match, which contains a variety of additional information but still keep the design minimalistic.
On the top, the avatar and username of the advertiser, the one who added the match, is displayed. There is an active link behind, if clicked, the user profile will be displayed. Furthermore the date when the event was last updated is shown, next to the edit icon.
Besides the displayed image, the main title of the match, together with the event date is shown. Further infos like the match location, IPSC Level, Division and match details are shown. Underneath that, the two active components attending with its attendings count as well as the comment and comments count are displayed. Their usage has already been explained in the matches section.
The comments section lets the users see all comments, the logged in user will also see the form to add a comment. The avatar is again an active link to the user's profile.
The user has also the option to edit or delete his comment. All comments of the logged in user will display the edit icon, which will give the option to edit or delete.
The comments section is also using the infinite scroll, displaying a loading spinner once more data is fetched from the API.
The Add Match icon on the navbar will redirect the logged in user to a form, where he can create a new match entry.
The form gives the option to add the following mandatory fields:
These fields are mandatory becasue without them, an advertisement of a match does not make sense...furthermore the application is based on "visuals", hence a match entry without an image would not be nice. The image upload is limited to max. 2MB or 4096 x 4096 pixels in order to stay within the Cloudinary's free hosting plan. If the user tries to submit the form and violating one of the mandatory fields, a respective error is displayed.
The following fields are optional:
Clicking on the cancel button will bring the user back to the site he came from.
If the owner of a particular match is logged in and has navigated to the match detail view of a particular match, he has the option to edit. The respective icon is only visible for the owner of the match and once clicked, the icon becomes active and displays the opton to delete or edit a match.
The delete functionality is straight forward, however in order to prevent unwanted deletion, a confirmation modal message is presenten upon pressing the delete button.
The user has then the choice to either cancel deletion or confirm it. Deleting the match entry will delete all related child entries like comments, attendings, ...
If the user decides to edit a match, he can do so via clicking the respective icon.
The edit form gets displayed where all the fields are pre populated with the existing data. The user can adjust any of them or choose to cancel the operation, which will bring him back to the match detail view. All the attendings or comments are kept in any case (updating or cancellign the update operation).
The Participating Shooters component, is a reusable component, which got added here.
This component displays all shooters who have clicked attend. It should give the user or a possible organisator / advertiser of a match, an overview on how many will attend and who. It is also interesting for fellow shooters, since some have preferences. The list can be extensively long, therefore I have implemented a limit in size. On desktop the component is allowed to grow max. to 400px in height, on mobile it is limited to only 90px height, which is just engough to display two rows of avatars. The rest of the content, if exceeding the limit, will be hidden and accessible via the scrollbar.
If the user clicks on an avatar, he will be redirected to the respective user profile component.
MySchedule is only accessible for a logged in user. It is not a component or a page by itself, it is only re-using existing parts and components. This showcases the beauty of such a React app.
It's look is almost identical to the Matches page, but this time it is optimised for a particular user. The MySchedule site, as the name implies, is personal. It will display all matches a particular user is attending. The main pourpose is to help the shooter to have a list of his upcoming events.
All filter functionality, including the additional featurs of attending an event or commenting on an event, remain the same as for the matches site. Clicking on a particular match, will bring the user again to the match detail view, which has been previously described. In addition to the personal schedule, alos the component with the Upcoming popular Matches is displayed again, which should help the shooter to see whether he is missing an popular event or not.
The MyGuns site is also only available for logged in user. Furthermore it is personal. A user cannot see content of another user.
This site acts as a personal database of the shooters own gun collection. It is not really related to the IPSC sport, he can add whatever gun he wishes. Many shooters are also in other clubs, for example for precision rifle shooting, long distance shooting. This part of the application should give the option to store and sort the collection.
The main component is the gun database entry itself, dispalying the add and updated fields. This can be great value, depending on how a collector is managing his collection. By default the list of guns is sorted with the most recent entry first. Below the image section, there is the brand and type field - probalby the most important fields. In addition to that, the type field (pre defined as either handgun or rifle) can be seen. The last field is the content field, where the user can add whatever he wants in order to describe the item.
On the top, the user gets displayed the (familiar) search and selection option. He can search based on a brand, model or serialnumber. The filter option is there to differentiate between handgun and rifle. If a user has a large collection, this can be a handy feature. Furthermore, filter and search can be combined.
Like in the match detail view, also in the MyGuns list as well as in the Gun detail view, the Upcoming popular Matches component gets reused. Since this site has its primary focus on matches listing, it should encourage the user as much as possible to attend as well. In a future version, another component will be added at this place, see Future Features section.
The Gun add icon, located in the navbar, will direct the logged in user to the gun create form.
Mandatory fields are
If these fields are not filled, an error message will be displayed.
The other fields are optional:
If the user decides to cancel, he will be redirected back to where he came from.
Once the user clicks on a particular entry in his gun database, he will see the details of such an entry.
The information, which he will be presented is pretty much the same as on the list view, but here he has the option to edit or delete an entry. The concept is the same like on match entry. If he selects deletion, a modal will be presented to ask for confirmation. Cancel will bring him back to the detail view.
The edit buton will open the edit form, with all the data pre populated. The user can edit all data, including the image. The cancel button will close the form and bring him back to the detail view.
The last section is the profiles site. The site itself is accessible for all visitors, even if not signed in. When the profile / avatar is clicked in any of the components as well as the navbar, the user will be displayed the profile page.
The difference between a signed in and a signed out user is, that once the user is signed in and visiting his own profile, he will be displayed the edit profile button.
The site displays the bio of the shooter aas well as some more club and shooter related information. As separate section with contact details is shown. The site will also display all matches, created by this particular user. This can be very handy and an alterntive way, besides the search functionality, to find content of a particular shooter. Clicking on a match event, will bring him to the match detail site.
The Upcoming popular Matches component is reused again. The functionality of it has been described previously.
Initially, once the user has signed up, all fields will be empty, so it is very much desired, that a user visits this section. The signed in user can edit his profile via clicking on the edit icon.
He is displayed with the option to edit his username, his password or the profile. Edit username or password will bring him to the respective form, where as its containing cancel button will bring him back to the profile section.
The edit profile section will let him update all the fields.
All of the profile edit form fields are optional, meaning no error gets displayed, if the user submits an empty form. This is intentionally correct because instead of pressing the cancel button, the user might just press submit. Also the avatar image is not mandatory, if not changed, the default image will be used further. The mail and social media fields contain a placeholder text, just to make sure the user will add them in the correct form. If not, an error will be shown - however, the fields can be left blank.
If the new user cancels the form submission or submits it empty, he will be sent back to the profile details. If everything is empty and he did not add a match yet, the empty logo will be displayed.
Certianly a profile update and submussion will result in updating the profile section as well as updating the avatar image on all components and related comments, match entries.
Keeping the deadline of this project in mind and also the agile approach of development, the current state covers a great MVP solution. However, the application can be improved in future product iterations. One feature in particular did not make it to the front end implementation and that was the usermessage feature. It is covered with the user stories
where as both of them would have been part of a new Shooters Component, covered with the stories
The aim should be to create a new component, dedicated to the shooters, listing all of them and give a variety of filter and choice field options. Furthermore it should act a the "direct messaging" center, where it is possible for a logged in user to send messages to another user. Maybe the whole idea could be transformed even futher into a live chat functionality.
Anyway, the back end part of the messaging feature got already implemented as a stretch objective of the DRF API project. In the README of the back end project, there is a chapter dedicated to the usermessages, including the related code. The code got removed on the final deployed project, since no unused code should be deployed.
In future iterations some more additional features could be implemented. Here some examples, which are on the list:
DateTime
formats. Even though I did some tweaking of the DateTime format in my app, via the back end in the Django REST part, in combination with the day adjustment including a dot (as described in this README), I want to bring it to a better, next level based on the back end.Asset.js (spinner)
The Asset
component is a reuseable component to display a spinner, an image, or a message based on the props passed to it.
spinner
prop is provided and set to true
, a spinner from the "react-bootstrap" library will be displayed.src
prop is provided, an image with that source URL will be rendered with the alt
attribute set to the message
prop's value.message
prop is provided, a paragraph text with the given message will be displayed beneath the image or spinner.The Asset
component uses some further styling, which is defined in the Asset.module.css
file. This component has been used widely in the application to display the loading spinner, while fetching more data from the API.
Avatar.js
The Avatar
component provides a reuseable component, mainly used in the app for the user profiles.
src
prop which stands for the image source URL for the avatar.45
pixels for the image which can be overridden with the height
prop. In the app, it gets overwritten on a few places.text
prop can be passed to display a label or description alongside the avatar image.The styling comes from the Avatar.module.css
file.
DeleteModal.js
The DeleteModal
component is used in two places of the application, when deleting a match or when deleting a gun object.
It uses the following elements
Hidden or Visible: It uses the show
prop to determine if the modal should be displayed or hidden.
Confirmation Prompt: The modal displays the question to the user – "Are you sure you want to delete this item?" – ensuring the user is aware of the consequenses when deleting the object.
User Actions:
handleClose
callback when clicked and the user will stay on the detail element (match or gun object), where he came from.handleConfirm
callback and will delete the object.I did not use any custom styling since I think the bootstrap styling for this modal looks great.
ErrorModal.js
The ErrorModal component serves as a notification system for displaying error messages to the user. Since it is not a nice and good idea to keep all the console.log elements in the code, I wanted to create something "useful" from user perspective. The try, catch
blocks are set, why also not using the catch
?
The ErrorModal
component serves as a notification system for displaying error messages to the user.
Visibility: Its visibility is managed by the show
prop. When show
is true
, the modal is visible, and when its false
, the modal is hidden.
Message: The modal displays a generic message – "Sorry, something went wrong! Try again later!" – which makes it suitable for general unexpected error scenarios.
Close Button: The modal includes a "Close" button, allowing users to dismiss the error message. This button triggers the onClose
callback
I did leave the styling to the default bootstrap modal styling, which I think looks good.
Integration into the App:
To provide centralized management of the error state and to make the modal accessible throughout the application, the ErrorModal
was integrated using React's Context API Link
Error Context Creation: An Error Context was created, which provides both the current error state and a function to set the error. This allows any component in the app to trigger the modal by setting an error. This was my target goal for creating this funcitonality, since I think it is a great use of the react context functionality....and it did force me to read the documentation for it
Provider Setup: The main App.js
file wraps the entire application inside the Error Context Provider
. This ensures that any component, regardless of its depth in the component tree, has access to the error state and the function to set an error. This was exactly, what brought me back to the iniital explanation of a context via showing the problem of "handing over functionality" down the tree
State Management: Within App.js
, a state variable is maintained to control the visibility of the ErrorModal
. Whenever an error is set, the modal is displayed, and the user can dismiss it using the onClose
functionality.
Utility: This setup allows any component in the application to display the ErrorModal
by simply updating the error context, making it a versatile and reusable error handling mechanism.
MoreDropdown.js
The MoreDropdown
component, provides a dropdown menu represented by the three dots (...
), visible on any content, where a user respectively the owner of an object, can edit it. It contains two main actions: "Edit" and "Delete". When clicked, each respective action is taken.
ThreeDots: This is a custom toggle for the dropdown menu. The use of React.forwardRef
ensures that the dropdown gets access to the DOM for positioning.
Dropdown Toggle: It uses the ThreeDots
component as the toggle button for the dropdown.
Dropdown Menu: This contains two items:
handleEdit
function.handleDelete
function.Profile Edit Dropdown
The ProfileEditDropdown
is a similar dropdown like the MoreDropdown
but specifically for the profile actions. Instead of general actions like the MoreDropdown
, it contains three actions that relate are used in the profile section: "Edit Profile", "Change Username", and "Change Password".
The component uses the useHistory
hook to handle navigation for each dropdown action.
The styling is handled by the MoreDropdown.module.css
file
NotFound.js
The NotFound
component is used to inform users that the page they're trying to access doesn't exist or cannot be found. This component provides a user-friendly response to potential navigation errors or mistyped URLs.
NotFound
component reuses the previously explained Asset
component, which displays an image and a message. Here, it's used to show a NoResults
image alongside a message: "Sorry, the page you're looking for doesn't exist".
It is a perfect example to show how the Asset component
can be usedStyling is defined in the NotFound.module.css
.
FormatDay.js
helperI did set the dateTime format already in the backend to a custom value. However, in the front end, I wanted that there is a dot after the day, like 13. Jun 2023. I am so used to this format, that I wanted to have it in my app.
So the FormatDay
function is an utility that formats the date string to include a dot after the day segment.
Input: This function takes in props
as its argument, which can have one of three date-related attributes: match_date
, updated_at
, or created_at
. These are the three date props, I have used throughout the app.
Functionality: The core functionality of this function is to append a dot (.) right after the day segment in a date string. It uses a regular expression /(\d+)/
to identify the day segment and then appends a dot to it.
Output: The function returns the newly formatted date string with the dot added.
If we look at the individual pages used for "MyGuns" as well as "Matches", they also make use of of reuseable components or elements. The Match.js
and the Gun.js
are also reused inside the pages. The "singular form", like Gun.js
is always the base, fetching the data. Then GunPage.js
and GunsPage.js
take it a step further, use other components like the ÀttendingShooters
or PopularMatches
, and integrate them.
The following custom hooks are used in this project
useClickOutsideToggle
The useClickOutsideToggle
is a custom hook, which provides a mechanism to handle the expanded state of our navbar dropdown compnent and toggles it off when a click is detected outside of the component.
It uses the React embedded hooks useEffect, useRef, useState
It initialises the state via the useState
hook and sets the value to false
. The useRef
hook also gets initialise with a value of null
, the ref will then be assigned to a DOM element.
The useEffect
hook adds the event Listener to the document, that check if there is a mouse Up event. Inside the handleClickOutside
function, it checks if the click event's target is outside the element referred to by ref
. If it is, it sets expanded to false.
The useEffect
also returns a cleanup function, which makes sure, that the event listener is removed when the component that uses this hook is unmounted or if the ref changes
The return value of the hook is the object with the expanded state
, the setExpanded
function to toggle this state, and the ref
that is assigned to the DOM element to detect clicks outside of it.
useRedirect
useRedirect
is another custom hook used in this project. It listens for changes in the user's authentication status. When there's a change, it tries to refresh the users authentication token. Depending on if thats a success or failure and the passed userAuthStatus, it redirects the user to the main route, which is the matches list.
The useRedirect
Hook takes a single parameter, userAuthStatus
, which indicates the user's authentication status. It makes use of the useEffect
hook, which contains an async function of handleMount
. A POST request is made to /dj-rest-auth/token/refresh/
to refresh the users authentication token. If the request is successful and the userAuthStatus
is "loggedIn", the user will be redirected to the root path, which is the matches list. If the request fails and hence, the user is logged out, it will also be redirected to the same root path.
It gets used on various places in the application.
There are a variety of libraries and dependencies required to run this project. The package.json
file contains a list of required packages, in order to have the deployed version used the correct ones. The following list is a summary of the packages, including a link to the reference and a short description.
git add
, git commit
, git push
)The following chapter describes how I made use of the very useful commit message feature.
At the final stage of the application, once doing the defensive programming tests, I did find quite some things, which are maybe not optimal. I have spent many hours trying to find solutions or alternative ways on how to tackle an issue. However, some things cannot just be changed, they would cause a redesign of the app.
One can say, that this is the lessons learned part and I somehow agree. I have learnt many things. For example I did not know until the end, that if I use react-bootstrap and "technically" just hide some content in the mobile view, it still gets rendered from a DOM perspective. So this fact causes some nasty problems and is also not very supportive for the loading time.
One particular change I did at the end I want to point out, is the following: I did change the behavior on how the MyGuns
site behaves. Initially I had the below visible code in it. It would cover the case that if an unauthenticated user is trying to access the guns site, via directly entering the url in the browser like /guns
, he would see a message telling: "You are not authorized to view this content. Create an account and login first."
However, I did not like that...I mean, this is just for a case, where the user is trying to do something, which he is not intended to do. Therefore I did implement current solution of redirecting the user back to the main route "/"
if he tries to do the above mentioned.
Now in such cases it would be nice to display a particular error Modal message, which brought me to the problem that my ErrorModal implementaiton would have to be refactored to accept dynamic inputs. I did not want to refactor this at the stage the app has been, fully tested and ready to submit. I did open a "future feature" for it.
Here the code snippet for the GunsPage.js
with the previously mentioned error message to be displayed (imports not included in the snippet).
You are not authorized to view this content.
Create an account and login first.
I have decided to mostly use multiline commit messages. Commit messages are an essential part of the whole project and a single line commit message is just not enough to explain. After reading this interesting article, it was clear to me, that I have to use it.
I have decided to use (mostly) multiline commits, but using tags as described this cheatsheet or as also described in the LMS of the Code Institute. I did use the following syntax guidline:
Github Projects has been used as the Agile tool during the development phase of this project. The Kanban board was very useful to keep track on the tasks. I have created columns (ToDo, In Progress, On Hold, Done) and moved the stories accordingly. The On Hold column has served as a "parking spaces", when a story was partially done, but not completely finished.
Github Issues has been used to create all the stories, before they were placed on the projects Kanban board. I have created an issues templates to simplify creation. Each issue has a label for the MoSCoW prioritization.
Once a story has been created via the template, it will be automatically added to the Kanban board in the Todo column.
The MoSCoW prioritization has been used to divide all epics and stories into the following categories:
A related Github label has been created for each category and added to each epic, story - which makes it easy to identify and see the value it brings.
Testing is covered in a separate page, view TESTING.md
The live deployed application can be found deployed on Heroku. Since the application is bound ot the Django REST API SportsShooting API, there is not direct database, media storage like cloudinary, ... needed. Everything gets consumbed via the API.
This project uses Heroku, a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.
Deployment steps are as follows, after account setup:
Heroku needs two additional files in order to deploy properly.
The package.json file gets automatically built, when you install a package via the npm install
command
The Procfile must contain the following command:
web: serve -s build
For Heroku deployment, follow these steps to connect your own GitHub repository to the newly created app:
Either:
Or:
heroku login -i
heroku git:remote -a app_name
(replace app_name with your app name)add
, commit
, and push
to GitHub, you can now type:
git push heroku main
The project should now be connected and deployed to Heroku!
This project can be cloned or forked in order to make a local copy on your own system. Depending on your local setup, npm needs to be installed. Do also make sure, that all required packages as mentioned in the package.json
file are installed on your local machine.
Depending on the node version you are using on the local environment, a workaround is needed to start the server via the npm start
command.
Before starting the server, the follwing command has to be entered, which tells nvm - the node version manager - the version he has to use.
nvm install 16 && nvm use 16
You can clone the repository by following these steps:
git clone https://github.com/rpf13/sportsshooting_react
Alternatively, if using Gitpod, you can click below to create your own workspace using this repository.
Please note that in order to directly open the project in Gitpod, you need to have the browser extension installed. A tutorial on how to do that can be found here.
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 owner's repository. You can fork this repository by using the following steps:
I have done lots of research, especially on the React side, to create this project. The following list will show some of the resources I have used. First and foremost, the Code Institute's own material, like the "Moments" walkthrough project, was extremely helpful and gave a general guidance, many of the taught concepts have been reused and adopted for my application.
Source | Location | Notes |
---|---|---|
Code Institute Tutorials | whole application | The code institute Moments Walkthrough tutorial was extremely helpful |
Very Academy React Project | whole application | I've watched a lot of the content from Very Academy |
React Context Handling | Error.context.Provider in App.js | Used to understand the context provider and how to add the error context provider |
React Hooks | whole application | I needed to read more about hooks in general |
Try Catch Error | whole application | I've used this MDN site to understand more about the try, catch, (finally) error handling |
React Bootstrap Modal | Modal | used to implement the modal for the delete verification |
React Functional Components | whole site | helped me to understand the concepts |
Components & Props | whole site | helped me to understand more about props. Really had some issues to understand that |
JS logial OR | whole site | used in the date formater, revisited this article |
JS replace | date formater | used this method in the date formater helper |
Conditional Ternary Operator | whole app | I had to read more about the conecpt, had some issues with nesting them |
Besides the CI content for jest tsting, I have used the following resources and articles for creating my Unit Testing for some of the components. In particular, the NavBar, the DeleteModal and the NotFound component have been tested via jest.
.toHaveBeenCalled()
as used in the DeleteModal LinkgetByText
as used in the Modal LinkfireEvent
LinkfindBy
LinkI have used the following media files and resources