Dynamic Temperature Unit & User Profile Feature

Job ID: 39204428

Budget: $30 – $250 USD

Step 1. Create the markup
We added a temperature toggle switch to the new Figma design:


Add a new ToggleSwitch component to your application and create the markup for the switch. Use the checkbox input type and implement custom styles for it according to the design.

This small piece of UI is more complicated under the hood than it would first seem. Although we could tell you how to implement it here, in the real world, you’ll often have to search around for solutions. Luckily, the React ecosystem is quite active, so examples of components are not hard to find. Here are a few to get you started:

For an explanation of how to set up a basic React checkbox component, check out this short tutorial.
For ideas on how to turn the checkbox into a toggle switch, check out this article.
Independently researching and implementing functionality like this is a critical skill for a software engineer. This is a great time to get some practice!

Step 2. Create a currentTemperatureUnit state in the root component
In the App component, create a currentTemperatureUnit state variable. Pass the string "F" as the initial value:

const [currentTemperatureUnit, setCurrentTemperatureUnit] = useState('F');
Step 3. Create a context object
To use context in our components, you may recall that we need to create a context object and wrap all elements that need to access the context in its provider.

We'll create the context object in a separate directory. To do so, create a contexts folder and add a new file called CurrentTemperatureUnitContext.js there. The file's path should look like this: src/contexts/CurrentTemperatureUnitContext.js. Export a new context object from this file.

Import this object into App and use its provider. Wrap all the current content of the root component with it. For the provider's value, pass an object with currentTemperatureUnit and handleToggleSwitchChange as properties.

<div className="page">
<CurrentTemperatureUnitContext.Provider
value={{ currentTemperatureUnit, handleToggleSwitchChange }}
>
{/* Contents of the App component */}
</CurrentTemperatureUnitContext.Provider>
</div>
Step 4. Extract a new value from the weather API
Previously, we extracted the current temperature value in Fahrenheit. To be able to use the value in Celsius, we need to extract it from the OpenWeather API as we did with the Fahrenheit value. (You can refer to the documentation if needed.) You can create a nested object for the temperature values:

weather.temperature.F = data.main.temp;
weather.temperature.C = Math.round((data.main.temp - 32) * 5/9);
Pay attention to the second line above. We receive a Fahrenheit value from the API and transform this value to Celsius.

Step 5. Use context in ToggleSwitch
Import the current unit context to the ToggleSwitch component and subscribe to it in order to get its value. Use the checkbox value and component state to toggle the measurement unit. When the checkbox is clicked, handle the toggle switch change by creating a corresponding method in App.js:

const handleToggleSwitchChange = () => {
currentTemperatureUnit === 'F'
? setCurrentTemperatureUnit('C')
: setCurrentTemperatureUnit('F');
};
Step 6. Use context in WeatherCard
Import CurrentTemperatureUnitContext into the WeatherCard component to get the context value.

Now you have the temperature unit value derived from the context. Use it to modify the temperature value displayed on the card. If you made the temperature object as we showed above, the following value can be displayed:

{weatherData.temperature[currentTemperatureUnit]}
Step 7. Use context in Main
We also display the temperature value in the Main component. Import it there and modify the displayed value.

Add a /profile route
We have a hardcoded username and avatar in the app header. You'll learn how to implement user authorization later in the program. For now, we'll prepare a hardcoded profile page for users using React Router.

Step 1. Create a new Profile component
The main page displays clothing items that match the current weather type. We can see from Figma that we need a place where we will see all the cards. The new Profile component will include two components inside:

SideBar displays the current user's username and avatar (still hardcoded).
ClothesSection displays all the clothing items from the current application state and includes a button that opens the AddItemModal component.
image

Step 2. Install React Router
npm install react-router-dom@6
Step 3. Configure routes
Configure routes in App.js for two paths:

/ for the Main component
/profile for the Profile component
Step 4. Add navigation links to Header
Use Link to turn the header elements into navigation links:

Clicking the logo leads to the main page (/)
Clicking the profile information leads to the profile page (/profile)
Complete the form for adding a clothing item
Finally, let's make our form add a new clothing item to the application state.

Step 1. Create the AddItemModal component
Create a new component called AddItemModal and import it into App.js. The contents of this component will be the corresponding ModalWithForm component and all of its children.

Handle the form data by the component's state by creating handlers corresponding to the onChange event of each state variable (name, imageUrl, weather).

Create a submit handler to prevent default behavior and call the corresponding onAddItem() method with the appropriate arguments:

// onAddItem refers to handleAddItemSubmit, which is declared in App.js
const AddItemModal = ({ isOpen, onAddItem, onCloseModal }) => {
// declare state for each input field

// use a useEffect hook to reset the input field state to empty strings when
// the modal is opened

// create onChange handlers corresponding to each state variable

function handleSubmit(e) {
// prevent default behavior
// call onAddItem with appropriate arguments
}

return (
{/* don't forget to pass appropriate props to ModalWithForm */}
<ModalWithForm>
{/* the contents of the form will go in here */}
</ModalWithForm>
);
};

export default AddItemModal;
Step 2. Save an item
Add the handleAddItemSubmit handler to App.js. In this handler, call the corresponding methods from api.js and update the clothingItems (your name may differ) state with an extended copy of the current array using the spread ... operator:

setClothingItems([item, ...clothingItems]);
If everything is working correctly, new items should appear at the beginning of the list. After refreshing the page, the new cards will disappear. To save them, we'll need a server with a database. (However, there's no need to think about saving cards just yet.)

Add functionality to delete cards
Step 1. Add a delete button
Add a delete button inside the ItemModal component according to the Figma design. When implementing the functionality to delete a card, you can choose from the following two options:

The card is deleted immediately when a user clicks on the delete button.
A confirmation modal is opened when the user clicks on the delete button (see Step 2 below). The card is only deleted after the user has confirmed the action.
In either case, the ItemModal component accepts the handler as a prop that takes the card object.

In case of immediate removal, the handler, which is passed from the App.js, will contain the corresponding API call. After a successful API request, the clothingItems state should be updated using the filter() method. You should also create a copy of the array and exclude the deleted card from it. Finally, remember to close the item modal window.

Step 2. Implement a confirmation modal (optional)
If you have decided to create a confirmation modal, follow the instructions here. There is nothing complicated about implementing a confirmation modal, and it will help your users avoid accidentally deleting their favorite cards.

Let's start by creating our markup for the modal. It should contain a warning message, as well as buttons to close, confirm, and cancel. The modal can be closed by clicking the "X" or the "Cancel" button. Clicking the confirmation button calls the handler, which is passed from App.

Besides the option to delete immediately, we now have two handlers in the App component. They are:

the openConfirmationModal handler, which is passed from the App to the ItemModal component, opens the confirmation modal, and saves a card to delete in the state.
the handleCardDelete handler, which is passed from the App to the DeleteConfirmationModal component. This handler makes the API call. After a successful API request, the clothingItems state needs to be updated, the modals closed, and the state containing the card should be reset.
Related categories: JavaScript CSS HTML React.js Server