Skip to content

mtmanning93/craft-front

Repository files navigation

Craft Social

Craft Social

Intro

Craft Social is a social platform where tradesmen and skilled workers can share work-related content. Showcasing their skills and abilities. It highlights good skills through people's approval within the industry.

This repository is for the Craft Social frontend. The application also utilizes a backend API using Django Rest Framework, the repository for this can be found at Craft-API.

Live Site

Hosted on Heroku

Repository

Github Repository

Project Stack

React, React-Bootstrap, JSX, CSS, HTML, axios

Get Started

To get started follow these steps to clone the GitHub repository locally, and setup other dependencies:

Deployment

Contents

Design Thinking

Problem ID


Tradesmen and manual workers often lack a dedicated platform to share their work and related information with other like-minded individuals who can appreciate it. Social media platforms like Instagram and Facebook are more geared towards free-time social activities and are not ideal for tradesmen. This lack of a dedicated platform is unfortunate, as tradesmen are often highly skilled individuals whose work is taken for granted due to the absence of a place to showcase it.

Problem Statement


"As a skilled tradesman, I would like to have a place to share work I am proud of or updates on a particular project, but I don't know where to share work-related content. Instagram is too social, and LinkedIn seems too corporate. This makes me feel my work is not getting seen or appreciated like other industries. Where can I share content, to showcase my skills for others to appreciate it."

Site Goals


User Goals - The user wants the ability to share work and work-related updates via a post, to a site with like-minded individuals, showcasing their craft and abilities.

Owner Goals - To create an environment for people with highly skilled manual jobs to share their work, showcase their skills, and have their work appreciated.

Brainstorm


After establishing the site goals, A brainstorming session was carried out. Many ideas were written down and the final brainstorm sheet took the best ideas discussed together, for better clarity during the build. Below is the final sheet.

Brainstorm sheet

⏫ contents

UX/ User Experience Design

User Stories


Once the main site functions and goals were decided on, user stories were created to clarify which tasks must be completed to reach the MVP (minimum viable product) of the site. Below are a few example user stories. To see all the user stories completed during the applications build, and those left within the product backlog, visit this link Craft Project Board.

Site Admin

"As a site admin I can control all site content so that I can keep the site content safe for all users."

User

"As a user I can move through the site easily so that my experience when moving through the site is without frustration."

"As a user I can view a list of all posts so that I have an overview of the entire site, and can easily select one to view more closely."

"As an unregistered user I can sign up to an account so that I can enjoy the benefits of a registered user."

"As a non-registered user I can view the comments left on each post so that I can read the conversation."

"As a user I can select a post and read its content so that I can read more information about it."

Registered User

"As a registered user I can login to my account so that i can use the registered user functions of the site."

"As a registered user I can navigate to the feed which shows all posts from users i follow so that I can see what these users are up to easier."

"As a registered user I can view a list of all posts I have liked so that I can see my favourite posts."

"As a registered user I can edit a published post so that its contents is how I would like."

"As a registered user I can login to my account so that i can use the registered user functions of the site."

⏫ contents

Wireframe


To aid in the design of the UI a wireframe was created. The preference was to create a large wireframe incorporating all pages, to visualize the flow of the website as well as the design. I provided wireframes for desktop/ laptop and mobile devices and the deletion confirmation modals.

Line Key:
Green - Creation or Addition
Orange - Action\

Full wireframe and flow of Reach website

⏫ contents

Information Architecture


When building the project's wireframe it was important to take into consideration the positioning of elements. Across the entire application, the user will find the consistent layout of a navbar and header above the main content, and an extra 'Work of the Week' app on the right-hand side of the main feed or object details. Key aspects of the information architecture found throughout the site are:

  • Site Wide Navbar:
    The navbar offers the user links to various pages of the site. For non-registered users simple 'home', 'login', and 'signup' links. Once logged in the navigation shows user-related links, such as the main 'Create Report (+)' button and the user avatar dropdown. The dropdown for each registered user contains links to profile, settings, and logout. The consistency of this navigation position aids the user in moving easily between user-specific parts of the site, contributing to a better user experience.

  • Branding:
    Within the navbar is a large site logo, this allows users to quickly identify the website and helps establish a visual identity. It's also a 'home' link when clicked, offering a return-to-home option wherever the user is in the site.

  • Header:
    The header contains a simple welcome message and an extra link to signup for unregistered users. For logged-in users the header contains links, in the form of tabs, to the different feeds of the site, it is consistently positioned throughout the application again to enable the user to navigate easily through the feed pages.

  • Work of the Week:
    The extra 'Work of the Week' (WotW) component is consistently positioned to the right of the main page details on desktops and at the top under the header for mobile devices. As one of the site goals is to showcase work this component had to be positioned in a clear, easy-to-locate place throughout the site.

⏫ contents

Visual Design


Color Scheme

The main colors used throughout the site were:

Color Palette

  • #000000
    • Used for fonts and borders. Provides high contrast against the backgrounds used throughout the site, creating better readability for the user.
  • #2a2a2a
    • The main content container background color, chosen for its high contrast when rendering other components on top. The 'concrete gey' color also represents a sense of stability. Which is relatable to the target audience.
  • #4682B4
    • The 'steel blue' color was used throughout the site as an accent color to highlight various items, mainly the user Avatar and the 'add company' button, representing trust and professionalism.
  • #f0ad4e
    • 'Warning yellow' catches the eye against the more plain background colors. It was used in the application to draw attention to important elements, such as the main action button component. Warning yellow is again relatable to the target audience as it often used in their industries to gain attention.
  • #f5f5f5
    • A light background color was needed for 'white space' in the site, to contrast against the main content background and dark fonts.

Fonts

The fonts chosen were imported from Google Fonts. The main font used throughout the site was 'Titillium Web'. Titillium Web is a versatile font that is easily adaptable to different font elements. Whether it's used in headings, subheadings, or body text, the font remains easy to read. As a sans serif font, it is simple and clear.

An example of Titillium Web in different font sizes

Icons

Icons were used throughout the site to assist the user in clarifying different actions and elements. They are a simple yet very efficient way to convey a message to the user. I used the Font Awesome library.

Example FA icons

Logo

A site logo was created using the Looka site. A site logo is an effective way for a user to immediately recognize the site's identity. Two logos were created for the site, a large named logo and a simple icon style logo, both were used in different situations, but mainly in the navigation bar as a link to home.

Large named logo Smaller icon logo

⏫ contents

Database ERD

An entity relationship diagram was created to assist in the visualization of the database structure. This visualization was important to clarify what data would be needed in order to provide the functionality desired within the application. Below is an image of the Created ERD with the relationships between models. A full rundown of the ERD and the database models within can be found in the Craft-API README/Database ERD

Craft Social API ERD

⏫ contents

Development

Agile Design


Due to the size, and the many different parts of the Craft Social project, it was crucial to adopt an Agile methodology. The project was split into two with a backend to compliment the frontend, adding to the complexity. In a project of this size, it can be easy to move between the tasks, skipping parts or even leaving them unfinished. With an Agile approach, it was possible to identify the key components and structure needed to build the MVP and separate them into more manageable tasks. Manual testing was carried out on each component to ensure it was working as expected before moving on to the next task. This method enforces regular reflection on the progress of the project.

Github Issues


Templates

Prior to the build process, three issue templates were created (more information can be found below):

Labels

At the beginning of the build after creating the issues, labels also needed to be created. The first labels created were to assign each template with a front or backend label, this helped to clearly separate tasks between the two project repositories. The repository labels:

  • frontend
  • backend (to read more about the backend label click here)

Next prioritising labels were created to define the importance of using the 'MoSCoW' principle, and separate the issues into groups. The labels were used when assessing each iteration, meaning they were not static from the beginning, they were reassigned when necessary to adjust the level of importance of the user story, throughout each iteration in the overall project. The 4 prioritising labels were:

  • Must Have
  • Should Have
  • Could Have
  • Wont have

To compliment the build process and reach the project MVP within the timeframe, other labels were created. All bug reports were naturally labeled with 'bug' and feature requests with the corresponding label. The labels were:

  • Bug
  • Feature Request

Project labels

⏫ contents

User Story Template

The first template created was the user story template. Every user story includes Acceptance Criteria and Tasks. The purpose of the user story was to begin the building process and help decide what features would be potentially included.

  • Acceptance Criteria: The acceptance criteria for a user story give a clear indication of what the expected outcome for the user is, it contains no technical information with regards to completing the user story. However, is clearly states what a user would expect in response.

  • Tasks: Once the user story was created and the acceptance criteria were assigned, the next step was to break it down into smaller tasks, all of which were achievable in a day or less. I created the tasks as a checkable list, making it visually clear, whilst developing the project, what the next step was.

Closed Issues list | Example user story

Bug Report

The next template created was the bug report. Whilst building the application and carrying out manual testing to check each component's acceptance criteria was met, occasionally, I would notice a 'Bug'. In order to keep the development flow I would create bug reports and add them to the list of issues, preventing being sidetracked. The bug reports were then addressed when the priority to do so was high, for example, when labeled a 'Must Have' within the current iteration.

If it was a bug within the current user story task I would assign the label 'Bug' to it.

Assigned 'Bug' label | Bug Report

Feature Request

The last template created was the feature request template. Whilst building such an application, or whilst demonstrating functionality to others ideas for new features would arise. Some of these ideas would clearly be a great addition to the application, however, applying them at that exact moment would slow down the overall production. Therefore adding feature requests to the product backlog meant they could be addressed once the MVP had been produced, or in the future versions of the application.

Example Feature Request

⏫ contents

Product Backlog


When creating new issues, bug reports, or feature requests they were added directly to the Craft Product Backlog. Once added to the product backlog it would be assigned the above-mentioned labels. Throughout the build as iterations were created, issues would be would be taken from the product backlog and into the relevant iteration, reassigning the labels according to the specific iteration priorities.

Craft Product Backlog

Iterations


In order to help manage the workload of the project, iterations were implemented using GitHub milestones to further breakdown the production and provide incremental delivery. This meant there was clear feedback as the project grew.

Each iteration was created with a due date. Allowing for adaptations throughout. An example would be that if a user story was not complete before the iteration due date it was returned to the product backlog for review of its importance, then reprioritized accordingly.

Working in iterations maintains a steady pace of work and keeps momentum throughout production. This is due to the constant assessment of progress.

Project Iterations

Backend Iteration

As the project consisted of two parts a front and backend I felt it was necessary to include a backend iteration, as the backend would ultimately enable the front-end functionality. To read more with regards to this iteration you can visit the Craft-API documentation.

Kanban Board


Before starting the production a Kanban board was created using Github Projects. Both the front and backend repositories were connected to the 'Craft Project Board', this enabled ease of access from both repositories and clear visualization of progress from the beginning.

The board was separated into 5 columns:

  • Backlog: the entire craft product backlog (all issues).
  • To Do/ Current Iteration: all issues in the current iteration.
  • Bugs: all issues with bugs found during the testing or development stage.
  • In Progress: all issues being worked on.
  • Done: all completed issues.

During the production the kanban board was constantly revised with issues moving between columns, this was the main reference point for the development process and daily tasks. Simply dragging an issue into the 'Done' column marked it as closed, however, when possible I would close an issue from the terminal using the close #<issue number> command from inside a commit message. This would automatically move the issue into the 'Done' column.

Craft Kanban Board

⏫ contents

Features

Current Features


Landing Page

When a user visits the site they are welcomed by a simple navbar giving options to home, login, and signup. A header containing a welcome message and brief information entice a non-registered user to sign up. Below is a feed containing all posts from the site and the 'Work of the Week' component, this gives a non registered user the ability to navigate around the site and read all information.

Landing Page Desktop Landing Page Mobile

⏫ contents

Sign Up Form

The sign-up registration form is simple, making it easy for unregistered users to sign-up with just a username and password confirmation. If a registered user finds themselves on the signup form there is also a login form link at the bottom to make navigate to the correct form easily.

Sign Up Form

⏫ contents

Login Form

Very similar to the signup form is the login form, registered users are able to login into their account quickly via a simple username and password combination. For non-registered users, there is a small link to navigate to the correct sign-up form if they have navigated to the wrong page.

Login Form

⏫ contents

Navbar

The navbar found at the top of the site contains user-related links to parts of the site. For unregistered and logged-out users the navbar holds links to home, login, and signup forms. When a registered user is logged in the navbar switches to contain the main '+' (add post) button along with their clickable avatar dropdown menu. Within this menu, a user can find a small welcome message along with links to their profile page, account settings (username and password), and a logout link. It is fully responsive from desktop to mobile collapsing down as the screen size gets smaller. The links in the nav have an active 'className' set to enable better site navigation for a user and finally the site logo is a clickable link to the home page.

Logged Out Nav Screenshots

Logged Out Nav Dekstop Logged Out Nav Mobile

Logged In Nav Screenshots

Logged In Nav Desktop Logged In Nav Mobile

⏫ contents

Footer

The Footer is found at the bottom of all site content. Inside the footer users can find a contact section, small message (including copyright) and extra avigation links. Its site role is to provide additional information, navigation, and functionality to the user, enabling a more user-friendly experience

Footer Screenshots

Footer Mobile Logged In Footer Desktop Logged Out Footer Desktop

⏫ contents

Header

A header component is found between the navbar and the main content of the site, for a logged-out or un-registered user it acts as a welcome header, providing snippets of information as to why they should sign up. For logged in users the header switches to feed navigation tabs. Users are able to quickly click between feeds, having the active feed visible as a tab when clicked. The tabs are responsive as on smaller screen sizes the text disappears showing only feed-related icons.

Logged Out Header Screenshots

Logged Out Header Dekstop Logged Out Header Mobile

Logged In Header Screenshots

Logged In Header Desktop Logged In Header Mobile

⏫ contents

Work Of The Week (WOTW)

As one of the site goals is to showcase all user's work and skills it was clear there needed to be a place to showcase popular posts. Therefore throughout the site, the WOTW component can be found on the right-hand side of the main content. It includes the top 3 most liked posts in smaller post forms, hiding some information. All of the posts in the WOTW are links to the related post details page, this means users can easily navigate to these posts. As other posts gain more likes they are replaced.

WOTW Desktop WOTW Mobile

⏫ contents

Discover Feed

The Discover feed is where all site content lives. This feed acts also as the landing page feed, enabling users to search around all site content, from here users are able to discover each other's profiles and posts. The posts are listed by the date of creation. All feeds use infinite scroll technology in order to create a better user experience by loading posts only when needed.

Discover Feed

⏫ contents

'Feed' Feed

This feed is only available to logged-in users and contains, all the posts, from all profiles they follow. Again using infintie scroll and listed by created date, in descending order. If a user is new or they haven't followed any profiles a message appears telling the user to 'get started by following other profiles' (an example can be seen in the liked feed explanation).

'Feed' (following) Feed

⏫ contents

Liked Feed

Much like the feed described above this feed is only available to logged-in users. It displays all posts a user has liked. Again if a user is new or they haven't liked any posts yet a message appears telling the user to 'get started by liking some posts'.

Liked Feed No posts message

⏫ contents

Top Feed

The Top feed is only accessible to logged-in users. It differs from the other feeds in that instead of displaying posts it displays profile cards. When the feed initially loads it lists all profiles in order of approval count, the most approved profile is awarded with the golden trophy on the top right of their profile card, second the silver medal, and third the bronze.

The idea of the top feed is for users to search profiles and have them listed in descending order of approvals. Users are able to search profiles by information on their profile cards. For example, if a user would like to find the most approved 'Landscaper' they can simply search this and have the profile cards listed with the most approved 'Landscaper' at the top of the list. Other examples include searching by employer, location, name, and username. Additionally beside the search bar is a hoverable information icon to explain in brief how a user can use the feed.

This works as a directory for users to find highly skilled individuals based on their needs.

Top Feed (Overall)

More Top Feed Screenshots

Top Feed (Overall) Mobile Example Top Feed Search Information Icon

⏫ contents

Search Bar

The search bar can be found above all feeds when a user is logged in. A user can use the search bar to filter feed results, if there are no posts found using this search filter a message is displayed.

Search Bar

⏫ contents

Create Post Form

A logged-in user has the ability to create a post via the yellow '+' button in the navbar. The button links to the create post form where a user can specify a title, content and add an image. Both the title and image are required to submit a valid form. Once a valid form is submitted the user is redirected to the post details page of the post they have just created.

Create Post Form Mobile Create Post Form Desktop '+' Create Button

⏫ contents

Edit Post Form

If a user owns a post object they will find an extra settings button on the post, with a spanner icon to make it distinguishable. When clicked it displays the option to edit the post. If a user clicks the edit option they are directed to the edit post form, this is the same as the create post form, just populated with the necessary post details. Here a user can update the post details.

Settings Button Edit Post Form

⏫ contents

Delete Objects

If a user owns a Post or Comment they will find the settings dropdown menu on the object itself. When clicked the object will show options to edit/ delete the object. If a user clicks the delete option a confirmation modal is shown, with further options to delete or cancel the deletion process. Only when the deletion is confirmed is the object deleted.

Delete Confirmation Modal Settings Dropdown Delete

⏫ contents

Post Details Page

When a user clicks on a post in a feed or WOTW they are directed to the post details page for the specific post, here a user can see the post in full size with a comments section beneath. If there are comments they can be read by the user. If a user is logged in they can interact with the post instance, both by liking the post and commenting on the post.

  • Liking

    On every post, a user will find a like button in the form of a 'thumbs up' icon. If the user is logged in they can click the button to like a post, naturally, the icon changes in response to this action, and clicking the button again will unlike the post. These actions in turn increment and decrement the like count accordingly.

    Like Button Unlike Button

  • Commenting

    In addition to the liking button, there is a comments icon displaying the number of comments next to it. If the user scrolls down they will be presented with a comment form. Here the user can write a comment in order to join the conversation of the post, by simply clicking the 'comment' button. Once posted the user will be able to see their comment listed below the post in order of most recent first. A user has the ability to delete the comment if they wish.

    Comments

⏫ contents

Profile Page

Throughout the site users can navigate to fellow users' profiles by clicking the avatar or personal information of a user, this can be seen on all posts. The profile page contains a profile card for every user which is populated with personal information and company information, which the user has added to their profile, this information could include:

  • name (not username)
  • craft
  • employer
  • location
  • bio
  • owned companies

This information can be added via the settings menu, more on this here.

Beneath the profile card is a feed of all posts created by the user in descending order of date of creation.

Profile Page Desktop Profile Page Mobile

  • Follow

    If a user is on a profile which is not their own, they can find an additional 'Follow' button. When clicking this button four things happen:

    1. the users following count increases by one
    2. the profiles follower count increases by one
    3. the follow button switches to an unfollow button
    4. the following profile posts are added to the 'Feed' feed.

    Of course, clicking the button again will simply reverse these effects.

    Follow Button Unfollow Button

  • Approve

    Similarly, a user can approve another profile using the approve button found on a profile, When clicking this button two things happen:

    1. the profile approval count increases by one
    2. the approve button switches to an approved button

    Again clicking the button again will simply reverse these effects.

    Approve Button Approved Button

⏫ contents

Update Profile

In order for a user to improve their profile and searchability within the top feed they can update their profile with additional information, they can do this by navigating to their profile and clicking the settings dropdown spanner, then selected edit. They will be directed to the update profile form. Where they can add additional profile data or update existing data, including profile image, adding companies they own, and selecting an employer.

Update Profile Form Desktop Update Profile Form Mobile

  • Select Employer

    One feature of the update profile form is an employer selection field. This selection dropdown is populated with companies created by other profiles. A user can select one of these companies as their employer or select no employer. The selection field is searchable making it much easier to find your employer if the site was to become populated with lots of profiles. When a user selects a company as their employer, the company's employee count increases accordingly. The employee count of companies can be seen on profile cards next to the owned companies of the profile in the 'Craft Employees' field.

    Employer Selector Employer Search Employee Count

  • Add/ Edit Company

    Beneath the personal information form, users can add up to three owned companies to their profile. Once added they can edit them or delete via the settings menu. If a user creates a company the company will be available in the employer selector field for all users, likewise if they delete the company the company will be removed from the selector and from all associated profiles employer field. Furthermore, users cannot create the same company multiple times, however, users must give a location when creating a the company this means that franchises in different towns or countries are possible.

    Add Company Edit Company

⏫ contents

Account Credentials

Users occasionally want to update their username or password to allow for this an updated credentials form was created, here a user can update either. The username is validated to check it hasn't already been used, and the passwords too must be the same and of correct length.

Update Credentials Form

⏫ contents

Company Directory

Users can scroll or search through the sites alphabetised list of companies. Clicking on a particular company in the list will open the company modal, which displays useful information regarding the company and a list of the companies employees, the employee list is also a clickeable linke to the related profile page. On mobiles it is located above the Top approved feed, whereas on desktops its easily found on all pages below the 'Work of the Week' component.

Company Directory Desktop Company Directory Mobile Company Modal

⏫ contents

CRUD Functionality


Craft Social features full Create, Read, Update, Delete functionality, for registered users, within the UI shown above in current features.

  • Create:

    Users can create posts, comments, likes, follows, approvals, and companies.

  • Read:

    Both registered and unregistered users have complete read functionality across posts, profiles, and comments.

  • Update:

    Posts, profiles, and companies can be updated within the UI.

  • Delete:

    All user-owned objects can be deleted with the UI. Including, posts, comments companies, likes, follows, and approvals.

⏫ contents

Future Features


The current released version of Craft Social was produced with a timeframe in mind, meaning the project scope was planned accordingly. Therefore in order to reach an MVP on time some features must be implemented in future versions. These features may be short or long-term, some future features are listed below:

  • Companies Directory

    In the future the companies directory could include contact details and website links, this would increase the visibilty of the users and potentially offer them work opportunities.

  • Company Contact Details

    In order to enable the above directory feature to work better, adding the company contact details would mean users can search companies by trade or by a particular profile and contact the company directly.

  • Delete Account

    Users will be able to delete there account with all posts and company instances in one click, logging them out in the process.

  • Swipe Through Feed

    On mobile and tablet-sized devices users could swipe left and right through the different feeds.

⏫ contents

Reusable Components

In a React application, seperating the UI into smaller components offers many benefits, such as code maintainability and development efficiency. Smaller components meant I was able to focus on specific functionalities or features, one at a time. Furthermore, these smaller components were reusable across the application, simplifying the development process. Additionally when components have bugs or changes need to be made its easier to pinpoint the issue, and fixing it often won't affect the other components in the application. Overall the use of smaller components created a cleaner codebase and more efficient production.

Below are examples of components that were reused throughout the build.

BackButton.js

Used throughout the application to provide the user with a go-back option.

MainButton.js

The main button component was used throughout to provide a better user experience, reusing this component meant all actions carried out by the user were controlled using the same button styling, different styles were available for use by adding the correct className, for example btnStyles.Wide was used to make the button full width in its container.

SettingsDropdown.js

SettingsDropdown component was used in a conditional statement across the application. If a user owned the object in question the SettingsDropdown would appear, it was used across, posts, profiles, comments, and companies. The dropdown offered options for edit or delete. The options were added to the dropdown when necessary in each use by adding the related props editObject={} and/ or onDelete={}.

InfiniteScroll.js

For all feeds infinitie scroll component was applied to enhance the user experience. Using this meant that page load was kept to a minimum speeding up the application as a whole.

Loader.js

It's important for users to never feel confused. Therefore whilst waiting for components to load a spinner is displayed to visualise the loading process. As the application contains many components a self defined Loader component became very useful.

ErrorAlert.js

A good user experience involves feedback to the user, therefore the application needed a way to display any error, or success, messages to the user. Having the error alert at hand meant calling it via the ErrorContext easy when needed in try and catch blocks.

Avatar.js

The avatar component was also useful. As a link to the profile of all users adding it to posts and comments was simple. In a use case, props were added to specify, src, height, textBefore, textAfter, className. Having two props for text positioning also canceled down on unnecessary CSS.

ConfirationModal.js

Whenever users wish to delete something it's important to get confirmation, ensuring they are not accidentally deleting something. The creation of the ConfirmationModal component means this process is easy to produce whenever a delete function is called. The use can be seen when deleting an object.

Post.js

Perhaps considered one of the main components of the application, a post component is displayed multiple times throughout. Often used as the response to a map() function, this means, that the more posts by users, the more Post.js components are used. Seperating this was imperative to the efficiency of the build.

Comment.js

Much like the Post.js component the Comment.js component is used as the response when 'mapping' over a list of results. Therefore having a separate component to use here makes the codebase more streamlined.

NavBar.js

Throughout the site the Navbar component is used for user navigation, it holds the logic to alter betweene a logged in state and logged out state, providing necessary links. It can always be found at the top of the site 'page'.

Footer.js

Similaraly to the NavBar component the Footer is always at the bottom of the page throughout the site, it holds contact links a small message and extra navigation links which, again, similar to the NavBar update on login.

CompanyList.js

Similar to he 'Work of the Week' component this feature component is used across all site pages which are not forms, simply by adding the component with no extra props or styles made it a great reuasable component.

⏫ contents

Contexts/ Hooks

ErrorContext.js

The application needed a notification system for error alerts initially, and further into the build a success alert. Using React's built-in context API, the ErrorContext was defined, this provided a way to share an error state, throughout the application. The context includes three functions and a state variable.

  • useErrorContext hook:

    This hook is used to access the ErrorContext. By calling useErrorContext() in a component, you can access the errorInfo state and use the three functions showErrorAlert, showSuccessAlert, and clearErrorAlert.

    • errorInfo - stores information about an error, such as the title, message, and variant (bootstrap variant e.g. warning).

    • showErrorAlert - the function used to display error alerts. It takes parameters for title, message, and variant, sets the error details, and triggers an error alert.

    • showSuccessAlert - function is similar to showErrorAlert but for success alerts.

    • clearErrorAlert - function resets the errorInfo state to 'null', effectively hiding any displayed alerts, used within the ErrorAert.js components timeout function.

  • ErrorProvider:

The component which serves as the provider for the ErrorContext. It wraps the entite application (App.js) with ErrorContext.Provider (index.js), making the state and functions available to all the nested components.

Creating this context, gave the ability to display error or success alerts throughout the application without having to pass down props through multiple components.

⏫ contents

CurrentUserContext.js

The CurrentUserContext was taken from the Code Institute Moments React walkthrough project. It is used for handling the current user's information. CurrentUserContext is used to share the current user data in different components. There's also the SetCurrentUserContext which is used to provide a function to update the current user data.

Additionally, there are the Axios interceptors which handle token refreshing. When making requests using axiosReq it checks if the token needs refreshing and automatically refreshes it when needed.

useRedirectUser.js

A custom React hook, taken from Code Institute Moments React walkthrough project, which handles redirection based on the user's authentication status. The logic means that by simply adding a line of code you can redirect unauthenticated users away from parts of the site. For example, a logged-out user shouldn't be able to access a create post form.

⏫ contents

Libraries and dependencies

  • react-bootstrap: Bootstrap was chosen due to its familiarity, speeding up development and making responsive design easier. Its library and documentation are extensive.

  • react-router: React router handles navigation in React applications, allowing for a dynamic and seamless user experience. It connects UI components with the applications Url's. Provides components like <Route> which can be found in App.js and is used for defining and managing routes of the components.

  • react-router-dom: An essential library for managing navigation and routing in React applications. In Craft Social it is used to enables basic routing like the navbar and header links to different 'pages'. It allows for such an application to become an SPA (single page application) which creates an overall better user experience. It also comes with 'out of the box' hooks, such as,useHistory(), useParams(), useLocation() which were used extensively throughout the project, and further sped up the development.

  • axios: A JavaScript library used for making HTTP requests, providing a simplealternative for sending and handling data requests. Again Craft Social relies heavily on axios for fetching data from and posting data to the API.

  • infinite-scroll: This library simplifies the implementation of infinite scrolling. Which creates a much more fluid user experience. It an easy to implement, straightforward way to detect scroll events and trigger data loading when the user reaches the bottom of a page. The addition of infinite-scroll made the user experience of Craft Social much more fluid.

  • react-select: A flexible and customizable dropdown/select component for React applications, allowing users to easily choose options from a list with features like searching, grouping, and styling. It enhances Craft Social by enabling an employer selection dropdown which users have the ability to search within.

  • jwt-decode: A JavaScript library used for decoding JSON Web Tokens (JWT) in web applications.

⏫ contents

Bugs

To view a list of all bug reports for the project bot resolved and unresolved got to Kanban with Bug Reports.

Resolved Bugs


As was expected with such a build some bugs were found and squashed here are some of the bugs which have been rectified, and a link to all closed bug reports.

  • axios defaults base URL was original set for the frontend Url not the API's

  • Edit post form not accepting populated image data on form submission.

    Initially when created the edit post form this had gone unnoticed, however later when manually testing the edit post form, I noticed that if a user wanted to change the text fields of the post and not the image the form wouldnt pass validation, raising validation errors. The bug was that the form wasn't allowing the user to submit the form without selecting another image. Below is the correct and incorrect code used:

    // Correct
    formData.append("image", imageSelection?.current?.files[0] || "");
    
    // INCORRECT ORIGNAL
    // formData.append("image", imageSelection.current.files[0] || profileData.image);
    
  • Assignments to the 'filter' variable from inside React Hook useEffect will be lost after each render.

    When trying to filter the list of posts for the following and liked feeds I needed to assign a filter method to each url. Originally I had defined the filter variable from inside the react hook, this raised a warning:

    src/pages/OtherFeeds.js
    Line 24:15:  Assignments to the 'filter' variable from inside React Hook useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside useEffect  react-hooks/exhaustive-deps
    
    // CORRECT
    useEffect(() => {
    
        let filter = ""
    
        const getPosts = async () => {...
    
    // INCORRECT
    useEffect(() => {
        const getPosts = async () => {
            try {
                if (currentUrl === "/feed") {
                    filter = `owner__followed__owner__profile=${user_id}&`;
                } else if (currentUrl === "/liked") {
                    filter = `like__owner__profile=${user_id}&ordering=-like__created_on&`;
                }...
    
  • Undefined ids on initial mount.

    When trying to fetch company lists based on a profile errors were being raised, this was because the function was trying to fetch data before the id was defined when mounting, to combat this I had to add an additionally line to check for a defined 'id' value before the try block:

    // CORRECT
    useEffect(() => {
        if (id !== undefined) {
            console.log("Before API request - id:", id);
    
            const getProfileCompanies = async () => {...
    
  • Navbar Avatar doesn't update on profile image update.

    When a user would update their profile image the Avatar's state was not updated meaning the users profile card would have one image but until the page was refreshed the navbar avatar wouldnt change. To fix the bug I needed to ensure a state change.

  • "401 Unauthorized" error on each key press when typing in Login and Signup forms.

    Whilst going through the site with a test user running the manual tests I quickly realised that whilst the user typed into the login form username field every key hit would, seem to, send an API request. For example every time a key was hit, including backspace, the 401 error was raised in the console. To debug this, I first included a console.log('componentDidRender') outside of the onChange function. It quickly became clear that the component was essentially re-rendering on every key press. To test this further I created a useEffect to run only once on mount, it looked like this:

    useEffect(() => {
        console.log('componentDidMount')
    }, [])
    

    This enabled me to see that the component was not remounting as the log would only show once on initial mount, however the componentDidRender was showing. After some research I understood that the previous 'loginData' state update was being updated on every key press, creating the rerender on every state update.

    To avoid using 'debounce' and 'throttling', to advanced techniques, I decided to search for the use of the useRef() hook in a form component, as I had previously used this hook. The search returned this result uncontrolled-inputs-react. I decided to test this out, as I understood the concept. The 401 errors were avoided and after testing the user could still, seemlessly, login.

    The same method was used on the signup form, the solution is to use the useRef hook over the useState as 'a way to store a mutable value within triggering a rerender'. For example:

    const usernameRef = useRef();
    const passwordRef = useRef();
    

    With this variables created I could assign them to a form input, like this:

    <Form.Control
        id="username-input"
        className={styles.Input}
        type="text"
        placeholder="Enter Username"
        name="username"
        ref={usernameRef}
    />
    

    Finally I used the current property of the ref to access the values from the input field, and post the form data to the '/login/' endpoint:

    const formData = {
            username: usernameRef.current.value,
            password: passwordRef.current.value,
        }
    const { data } = await axios.post(
    		"/dj-rest-auth/login/",
            formData
    	);
    

    To see it in full use in the application it can be found at: src/pages/forms/LoginForm.js / src/pages/forms/SignUpForm.js

⏫ contents

Unresolved Bugs


Due to the time constraints there were some bugs which were not addressed although they do not directly affect the applications overall functionality and were not essential for the MVP, here is a link to all unresolved bugs.

Remounting due to ErrorProvider updating.

To improve the overall user experience I created an ErrorContext to pass errors to a notification system, which would display both Error messages and success messages as a bootstrap alert in the viewport. The system works as expected and it made for a less verbose catch statement throughout the applications components. Making the development process again more streamlined.

The unresolved bug occurs when updating a components state, for example editing a post. When the edited post is submitted a user is redirected and a success message displayed. However after the timeout of the ErrorAlert component the parent component of the updated post will again rerender. To simplify the parent element renders twice. This does not affect the outcome and at both renders the component displays the correct data.

After much debugging, it became apparent that the issue was down to the ErrorProvider which wraps the entire <App />. After the ErrorAlert has timed out the ErrorProvider then also updates. Although initially it was thought to be down to the timeout on the ErrorAlert

In future versions this error can be rectified with a complete restructure of the ErrorContext and alert system. However due to time constraints this has not become a priority for the MVP release.

Error Report

Deleting of a profile/ account.

A feature request to be able to delete an account was attempted. The functionality must include deleted the profile instance, user instance and logging the user out in one click. After a first implementation it would delete a profile but keep them logged in, this would cause unauthorization errors on the site and meant I would need to clear cookies and data in the browser before refreshing. In future versions this would be a great addition, however, for the MVP it is not essential.

Error Report

⏫ contents

Deployment

Github Cloning


If you have also cloned and deployed your own version of the TribeHub Django Rest Framework API, you will need to ensure the value of axios.defaults.baseURL in src/api/axiosDefaults.js is set to the base URL for your API. Pull to your local development environment and push back to GitHub if necessary; otherwise, leave as is to use the original TribeHub API.

Fork or clone this project from its GitHub repository, follow the steps below:

1. Navigate to the craft-front repository, and click the green 'code' button.

Clone button in repo

2. Once clicked, within the dropdown, fork or clone this project, here we will clone using the url.

Clone url

3. In your local IDE open your Git terminal

4. Change your working directory to your preferred location.

5. Next type the following command, the 'copied URL' is the URL taken form the Github repo.

git clone https://github.com/mtmanning93/craft-front

6. Hit Enter to create the cloned repository.

7. Either use the original Craft Social API by making no changes. If you have cloned and deployed your own version of the Craft-API using DRF, you must update the axios.defaults.baseURL found in src/api/axiosDefaults.js to the url of your deployed API

axios.defaults.baseURL = "<API URL>";

⏫ contents

Heroku Deployment


The application was deployed using Heroku. Heroku simplifies the deployment process. With a few commands, you can deploy your application without the need to configure servers, networking, or infrastructure.

In order to deploy Craft Social to Heroku I followed these 8 steps:

1. Navigate to the Heroku dashboard. Click "New" and select "Create new app".

Create new app

2. Create an app name and select a region closest to you.

Giving the app a name

3. Navigate to the 'Deploy' tab.

Deploy tab

4. Scroll to the 'Deployment Methods' section and select 'Connect to GitHub'.

Step one connect to GitHub

5. Once connected to GitHub, search for the repository in the 'Connect to GitHub' section, and click 'Connect'.

Step two connect to Github

6. I chose to enable 'Automatic Deploys'. In order to do so click the 'Enable Automatic Deploys' button.

Enable automatic deploys

7. For manual deployment use the 'Manual Deploy' section by clicking 'Deploy Branch'.

Manual deploys

8. Click 'View' at the bottom of the 'Manual Deploy' section to view the deployed project.

View deployed site button

⏫ contents

Credits

Tools


Resources


  • Code Institute 'Moments' Walkthrough was used throughout the build as a reference and for specific use cases, which are documented below:

    • Current user context hook (src/contexts/CurrentUserContext.js)
    • The use of axios interceptors to refresh tokens (src/api/axiosDefaults.js)
    • Click outside toggle functionality (src/hooks/useClickOutsideToggle.js)
    • Redirect users based on authentication (src/hooks/useRedirectUser.js)
    • Form validation alerts (site wide, example: src/pages/forms/LoginForm.js)
  • Using useRef over useState to avoid 401 errors from onChange rerender more information (link to Resolved Bugs) - Uncontrolled Inputs React

  • Infinite Scroll - Npm react-infinite-scroll Docs

  • React Select - React Select Search Docs

  • To fix click outside custom dropdown (src/components/NavBar.js) - Close Dropdown Link

  • Using 'isMounted' to avoid the 'can't perform a React state update on an unmounted component' warning (src/components/WorkOfTheWeek.js, src/pages/forms/EditCompanyForm.js) - isMounted Thread

  • Using ref to store a reference to the current timeout (src/components/tools/ErrorAlert.js) - Timeout Updating State, Clearing Timeouts

The below Docs were used extensively throughout the project build:

Tutorials


⏫ contents

⏩ Testing.md

⏪ Craft-API Repository