<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SimoneVeitch</title>
    <description>The latest articles on DEV Community by SimoneVeitch (@simoneveitch).</description>
    <link>https://dev.to/simoneveitch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1413475%2F875c9399-74f8-4301-8ad5-f0a3ffe41362.png</url>
      <title>DEV Community: SimoneVeitch</title>
      <link>https://dev.to/simoneveitch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/simoneveitch"/>
    <language>en</language>
    <item>
      <title>Navigating Client-Side Routing</title>
      <dc:creator>SimoneVeitch</dc:creator>
      <pubDate>Wed, 19 Jun 2024 05:03:22 +0000</pubDate>
      <link>https://dev.to/simoneveitch/navigating-react-client-side-routing-5cnb</link>
      <guid>https://dev.to/simoneveitch/navigating-react-client-side-routing-5cnb</guid>
      <description>&lt;p&gt;Hello readers,&lt;/p&gt;

&lt;p&gt;I'm Simone, currently enrolled in the Academi Xi Front-End Web Development: Transform course. I'm in the midst of Phase 2, which focuses on React.&lt;/p&gt;

&lt;p&gt;After completing Phase 1, which laid the foundation for Javascript, Phase 2 introduced me to the world of React. &lt;/p&gt;

&lt;p&gt;It took some adjustment moving from a vanilla Javascript mindset, to suddenly having to think in components, states and side effects. The biggest challenge I faced, however, was client-side routing. &lt;/p&gt;

&lt;p&gt;I’ll tell you why. &lt;/p&gt;

&lt;p&gt;Prior to being introduced to client-side routing the two main concepts that I was introduced to were useState and useEffect. While it took some time to get my head around these two hooks, they are more straightforward in their use.  &lt;/p&gt;

&lt;p&gt;Client-side routing introduced multiple concepts that I had to get my head around in a very brief amount of time. You need to understand all the components that make up client-side routing to get it to work on your web application and be able to troubleshoot issues that you will no doubt face when trying this out for the first time.    &lt;/p&gt;

&lt;p&gt;But first things first, why is client-side routing important? Client-side routing enables smooth navigation between different pages on your web application without making a full request to the server. This is beneficial as it leads to a faster user experience when navigating between pages. &lt;/p&gt;

&lt;p&gt;In vanilla Javascript you will typically need to click on a link that points to a different HTML file, ie, loading an entirely new HTML document. To do this the browser has to send a request to the server for the new page, which can lead to a less smooth user experience. &lt;/p&gt;

&lt;p&gt;Alternatively, to avoid a full page reload using vanilla Javascript, you can use Javascript to manipulate the DOM and update the content, but as it requires manual handling of the DOM it is more error prone. &lt;/p&gt;

&lt;p&gt;While I personally find using vanilla Javascript for page navigation more simple and approachable as an aspiring front-end web developer, the benefits of using React and client-side routing outweigh those of vanilla JavaScript (if, and only if, you are building an application where page navigation is necessary).&lt;/p&gt;

&lt;p&gt;React uses a single-page application approach, and handles routing within this, which allows for a more seamless navigation. This approach avoids full page reloads, and navigation is instead managed by React components. &lt;/p&gt;

&lt;p&gt;Below I will take you through some key concepts relating to client-side routing with code examples from my Phase 2 React web application project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get started using client-side routing you will need to install React Router, which is a library that handles routing in React applications. Without this you won’t have the components and hooks required to manage navigation and URL changes. &lt;/p&gt;

&lt;p&gt;In your terminal add the following to install React Router&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, import it into your application in the component where you need to enable client-side routing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me break this down before we continue. &lt;/p&gt;

&lt;p&gt;BrowserRouter is the top level component that enables routing. It uses the  HTML5 history API to manage the browser’s history stack, which is what allows you to navigate through your app using the browser's back and forward buttons. &lt;/p&gt;

&lt;p&gt;Next, you need to wrap your components and routes in &lt;code&gt;&amp;lt;Router&amp;gt;&lt;/code&gt; to be able to define routes and navigate between them without refreshing the page. You typically just need to do this in your top-level Router component, which in my case is index.js. You only need to do this once, as the &lt;code&gt;&amp;lt;Router&amp;gt;&lt;/code&gt; component provides routing context to all its child components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
import App from "./Components/App";
import './index.css';


ReactDOM.render(
&amp;lt;Router&amp;gt;
  &amp;lt;App /&amp;gt;
&amp;lt;/Router&amp;gt;,
document.getElementById("root")
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have that set up, we can start working on our routing context. &lt;/p&gt;

&lt;p&gt;In my web application I have two main components that work with navigation, App and NavBar.&lt;/p&gt;

&lt;p&gt;Starting with my App component, I import all the components that I want to navigate to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NavBar from "./NavBar";
import DirectoryList from "./DirectoryList";
import ResultsList from "./ResultsList";
import Contact from "./Contact";
import Tips from "./Tips";
import Home from "./Home";
import Footer from "./Footer";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then wrap all my routes in &lt;code&gt;&amp;lt;Switch&amp;gt;&lt;/code&gt;. The purpose of switch is that it ensures that only the first matching &lt;code&gt;&amp;lt;Route&amp;gt;&lt;/code&gt;is rendered. This prevents multiple components from rendering at the same time, which is important to ensure a smooth user experience. &lt;/p&gt;

&lt;p&gt;Next I wrap each component that will sit on its own page, ie, each component that I want the user to be able to navigate to, as though it’s its own page in &lt;code&gt;&amp;lt;Route&amp;gt;&lt;/code&gt;. &lt;code&gt;&amp;lt;Route&amp;gt;&lt;/code&gt; defines the paths and the components to render for those paths. For example, when the URL in my code is &lt;code&gt;/directorylist&lt;/code&gt;, the DirectoryList component is rendered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (
     &amp;lt;div className="app-container"&amp;gt;
       &amp;lt;NavBar /&amp;gt;
       &amp;lt;Switch&amp;gt;
         &amp;lt;Route exact path="/directorylist"&amp;gt;
           &amp;lt;DirectoryList list={list}/&amp;gt;
         &amp;lt;/Route&amp;gt;
         &amp;lt;Route exact path="/tips"&amp;gt;
           &amp;lt;Tips /&amp;gt;
         &amp;lt;/Route&amp;gt;
         &amp;lt;Route exact path="/contact"&amp;gt;
           &amp;lt;Contact onAddOrganisation={handleAddOrganisation}/&amp;gt;
         &amp;lt;/Route&amp;gt;
         &amp;lt;Route exact path="/"&amp;gt;
           &amp;lt;Home /&amp;gt;
         &amp;lt;/Route&amp;gt;
         &amp;lt;Route
           path="/results/:category"
           render={({ match }) =&amp;gt; (
             &amp;lt;ResultsList category={match.params.category} /&amp;gt;
           )}
         /&amp;gt;
       &amp;lt;/Switch&amp;gt;
       &amp;lt;Footer /&amp;gt;
     &amp;lt;/div&amp;gt;
 );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few props that make &lt;code&gt;&amp;lt;Route&amp;gt;&lt;/code&gt; work as it does. You can see them all in use here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Route exact path="/directorylist"&amp;gt;
           &amp;lt;DirectoryList list={list}/&amp;gt;
         &amp;lt;/Route&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Path is the URL path to match, ‘exact’ ensures that the route matches exactly, preventing partial matches. This is especially important if you have a path that is &lt;code&gt;“/”&lt;/code&gt; like I do for the Home component. And then there is the component to render, when the path matches, which in the above example is my DirectoryList component. &lt;/p&gt;

&lt;p&gt;That concludes the routing context in my App component. In summary, the &lt;code&gt;&amp;lt;Router&amp;gt;&lt;/code&gt; set up manages the routing context and determines which components to render based on the current URL. &lt;/p&gt;

&lt;p&gt;This isn’t where the story ends though, next you need to set up the UI elements for navigating between the different routes, without that your users won’t be able to actually navigate to the different components. In my case, I manage this in my NavBar component. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigation interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To start off, I again first need to import the component that enables rendering. &lt;/p&gt;

&lt;p&gt;If you don’t plan to do any styling based on active routes you can import &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;, but as I am, I imported &lt;code&gt;&amp;lt;NavLink&amp;gt;&lt;/code&gt; instead. Both components render an anchor tag &lt;code&gt;(&amp;lt;a&amp;gt;)&lt;/code&gt; and update the URL without causing a page reload. The difference is that with &lt;code&gt;&amp;lt;Navlink&amp;gt;&lt;/code&gt; you can define styling for the active route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NavLink } from "react-router-dom";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I add all the NavLinks that will appear in my navigation bar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 return (
   &amp;lt;div className={`navbar ${navBackground ? "navbar-scrolled" : ""}`}&amp;gt;
       &amp;lt;button className={`hamburger ${menuOpen ? "open" : ""}`} onClick={toggleMenu}&amp;gt;
               &amp;lt;div className="line"&amp;gt;&amp;lt;/div&amp;gt;
               &amp;lt;div className="line"&amp;gt;&amp;lt;/div&amp;gt;
               &amp;lt;div className="line"&amp;gt;&amp;lt;/div&amp;gt;
           &amp;lt;/button&amp;gt;
           &amp;lt;div className={`nav-links ${menuOpen ? "open" : ""}`}&amp;gt;
     &amp;lt;NavLink to="/" exact className="navlink" activeClassName="active"&amp;gt;
       Home
     &amp;lt;/NavLink&amp;gt;
     &amp;lt;NavLink to="/directorylist" exact className="navlink" activeClassName="active"&amp;gt;
       Directory
     &amp;lt;/NavLink&amp;gt;
     &amp;lt;NavLink to="/tips" exact className="navlink" activeClassName="active"&amp;gt;
       Tips
     &amp;lt;/NavLink&amp;gt;
     &amp;lt;NavLink to="/contact" exact className="navlink" activeClassName="active"&amp;gt;
       Contact
     &amp;lt;/NavLink&amp;gt;
   &amp;lt;/div&amp;gt;
   &amp;lt;/div&amp;gt;
 );
}


export default NavBar;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To break down the elements in the code above, the NavBar component provides a user interface for navigation, which is imported into my App components that renders that component.  The NavLinks are used to create navigable links that allow users to switch between different routes, and it also enables me to add styling to the link when it matches the current URL.&lt;/p&gt;

&lt;p&gt;I can then define the active style in my CSS, providing a better user experience as the user will know which route is active. &lt;/p&gt;

&lt;p&gt;The screenshot below is from my web application, and when a route is active, ie, is the page the user is currently on, the nav element has an underline. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84xoggt3d4z71aketcmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84xoggt3d4z71aketcmt.png" alt="Image description" width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is that. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final words&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In summary, I need both the Router setup in my App component for routing logic and the NavLink setup in my NavBar component for navigation UI, to ensure that users can interact with my app and navigate between different pages smoothly.&lt;/p&gt;

&lt;p&gt;These are the most fundamental parts of client-side routing. There are other hooks that are important, like useParams and useLocation, but I won’t go in to those here. &lt;/p&gt;

&lt;p&gt;Thanks for reading. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>My flip gallery journey</title>
      <dc:creator>SimoneVeitch</dc:creator>
      <pubDate>Mon, 15 Apr 2024 05:32:26 +0000</pubDate>
      <link>https://dev.to/simoneveitch/my-flip-gallery-journey-282i</link>
      <guid>https://dev.to/simoneveitch/my-flip-gallery-journey-282i</guid>
      <description>&lt;p&gt;Hello readers,&lt;/p&gt;

&lt;p&gt;I'm Simone, currently enrolled in the Academi Xi Front-End Web Development: Transform course. I'm in the midst of Phase 1, which focuses on JavaScript. &lt;/p&gt;

&lt;p&gt;During this phase, I've gained a solid understanding of fundamental JavaScript concepts. I've learned how to manipulate the DOM, handle JavaScript events, and interact with the server using json-server.&lt;/p&gt;

&lt;p&gt;At the end of this phase, all students, including myself, are tasked with creating a web application that demonstrates our grasp of the concepts covered so far. Additionally, we're required to write a blog post focusing on a technical aspect of front-end web development. This post is my attempt to fulfill that requirement.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk you through the development of the key feature of my web application. This feature integrates all the elements of my learning journey thus far, including HTML, CSS, DOM manipulation, JavaScript events, and server communication.&lt;/p&gt;

&lt;p&gt;But before we delve into that, let's start from the beginning of my web application journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s a data thing
&lt;/h2&gt;

&lt;p&gt;For my Phase 1 web application project, I had to build a frontend using HTML, CSS, and JavaScript that interacts with data&lt;/p&gt;

&lt;p&gt;Before diving into the actual coding and visual design of my app, I had to work out what kind of data I was going to use. &lt;/p&gt;

&lt;p&gt;Throughout Phase 1, we primarily used animal-related data, particularly relating to cats or dogs. Given this familiarity, I decided to start with this type of data for my project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExeDZ3bWkwOHJsaXAzdXNpcmNuZzFlaWduZThlbnJhZXA0d3h0d2hlNCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/G1ifnX4d5tYFACktp9/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExeDZ3bWkwOHJsaXAzdXNpcmNuZzFlaWduZThlbnJhZXA0d3h0d2hlNCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/G1ifnX4d5tYFACktp9/giphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While exploring public APIs, I found that many of them provided only limited information, such as images or a single attribute like breed or name. This posed a challenge, as our project required us to use an API that returned a collection of at least five objects, each with at least three attributes. To address this, I opted to create my own db.json file to serve as the data source for my project.  &lt;/p&gt;

&lt;p&gt;Now that I knew where I would get my data from, I had to decide what kind of data I wanted to use and with that, what kind of web application I wanted to build. &lt;/p&gt;

&lt;h2&gt;
  
  
  Furry friends
&lt;/h2&gt;

&lt;p&gt;Continuing with the pet theme, I chose to focus on dogs for my project since I lean more towards being a dog person than a cat person. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMGhxb2dnanlpczZsaHNmbWtnbTEwYzIwZXN1ZGNpZGhkMHJzM2xuNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/QsbJdgYL5BRafgRG2Z/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMGhxb2dnanlpczZsaHNmbWtnbTEwYzIwZXN1ZGNpZGhkMHJzM2xuNSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/QsbJdgYL5BRafgRG2Z/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, working with pet data was a familiar choice, as mentioned earlier.&lt;/p&gt;

&lt;p&gt;I knew I had to display data in an interesting way, use at least three distinct event listeners that enable interactivity and implement at least one instance of array iterations. &lt;/p&gt;

&lt;p&gt;What would be a good way to do this…. A dog competition site of course! I called the web application, and the competition, Furry Fave 2024. In the competition fictional judges and users decide who should win Furry Fave 2024, i.e. who is the cutest, and most likeable dog. &lt;/p&gt;

&lt;p&gt;With only eight weeks of JavaScript learning under my belt the app is fairly simple. On the site users can scroll through a gallery of the dog’s that are in the competition to be Furry Fave 2024, they can like their favourite dog, they can see who the leading puppy is (the dog with the most likes to date), and they can submit a dog to the competition.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjlrYW9uemdwcmsyejJsdGJ0bGJzaWh1NG1zN3c4MDc5OGxwMW9wayZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/w4QCwN33PV26vSn1db/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjlrYW9uemdwcmsyejJsdGJ0bGJzaWh1NG1zN3c4MDc5OGxwMW9wayZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/w4QCwN33PV26vSn1db/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of elements to the app, but for today’s post I will focus on the key feature of the app; the contestants gallery. &lt;/p&gt;

&lt;h2&gt;
  
  
  Back to the &lt;del&gt;future&lt;/del&gt; data
&lt;/h2&gt;

&lt;p&gt;I wanted to display dog data in a visually interesting way that would encourage interactivity, while meeting the project requirements. I thought a gallery would be a good way to do this. &lt;/p&gt;

&lt;p&gt;Going back to data, before delving into HTML, CSS or JavaScript I needed to decide what data I wanted to display on my app and create my db.json file. &lt;/p&gt;

&lt;p&gt;To ensure the gallery was visually appealing, informative, and met the requirement of returning objects with at least three attributes, I decided that each dog should have the following attributes: id, image, name, breed and description. To then encourage interactivity I also added a like attribute as I knew I wanted a like button for each dog. In the data set the like attribute shows the total likes to date, a number I initially add, but which will increase dynamically.. I will get back to that. &lt;/p&gt;

&lt;p&gt;In the end, the data structure for each dog in my db.json file looked like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "dogs": [
   {
     "id": "1",
     "image": "https://www.purina.co.uk/sites/default/files/styles/square_medium_440x440/public/2022-07/Spaniel%20%28American%20Cocker%291.jpg",
     "name": "Vanilla",
     "breed": "Cocker Spaniel",
     "description": "Vanilla is a merry and busy little dog. Profuse and glamorous,  she is an intelligent dog who loves her family",
     "likes": 13
   } 
]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To ensure that the data I used would display on my published site, once I had added enough starting data in my db.json file I deployed my json-server on render.com. That deservers a separate blog post, but I won't go much further in to that today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Javascripting away
&lt;/h2&gt;

&lt;p&gt;With my data in place it was time to roll up my sleeves and dig into some JavaScript code. &lt;/p&gt;

&lt;p&gt;I had the structure and hierarchy in place for my app, so the first thing I had to do was create a place for the gallery in my HTML file within that hierarchy. &lt;/p&gt;

&lt;p&gt;In my HTML file I created a cards div container to hold the card elements that would be dynamically created using JavaScript. I gave the div a class to be used for CSS purposes later, and placed this div within the main contestants section on the site. As you can see there is no content within the div, that is because the content will be dynamically generated through JavaScript in interaction with the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section id="contestants"&amp;gt;
       &amp;lt;h2&amp;gt;&amp;lt;span class='bark'&amp;gt;CONTESTANTS&amp;lt;/span&amp;gt;&amp;lt;/h2&amp;gt;
       &amp;lt;div class="heart"&amp;gt;
           &amp;lt;img src="./Images/noun-footprint-3974617.png" alt="dog heart paw"/&amp;gt;
           &amp;lt;img src="./Images/noun-footprint-3974617.png" alt="dog heart paw"/&amp;gt;
       &amp;lt;/div&amp;gt;
       &amp;lt;div id="cards" class="card-gallery"&amp;gt;
       &amp;lt;/div&amp;gt;
   &amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I moved on to my index.js file, where I added a function to render each dog card to be displayed in the gallery. I called this function renderOneDog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function renderOneDog(dog) {
   const card = document.createElement('div');
   card.className = 'card';
   card.innerHTML = `
       &amp;lt;div class="card-inner"&amp;gt;
           &amp;lt;div class="card-front"&amp;gt;
               &amp;lt;img src="${dog.image}" class="dog-image" /&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;div class="card-back"&amp;gt;
               &amp;lt;h3&amp;gt;${dog.name} the ${dog.breed}&amp;lt;/h3&amp;gt;
               &amp;lt;p&amp;gt;${dog.description}&amp;lt;/p&amp;gt;
               &amp;lt;p class="like"&amp;gt;${dog.likes} likes&amp;lt;/p&amp;gt;
           &amp;lt;/div&amp;gt;
       &amp;lt;/div&amp;gt;
       &amp;lt;button class="like-btn" data-id="${dog.id}"&amp;gt;Like&amp;lt;/button&amp;gt;
   `;
   card.querySelector('.like-btn').addEventListener('click', handleLike);
   document.querySelector("#cards").appendChild(card);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The renderOneDog function takes a dog object as input and creates a new div element (card) for each dog. By passing a dog object to the function, it can access these properties and use them to dynamically create a card with correct/up to date information. &lt;/p&gt;

&lt;p&gt;The card sets the class name of the card to card and populates its HTML content with the dog’s image, name, breed, description and number of likes. &lt;/p&gt;

&lt;p&gt;The function also adds a like button (like-btn) to each card for liking the dog, with the dog’s ID as a data-id attribute. This is used to uniquely identify each dog in the gallery, which is important as the function that handles likes (which I will get to), needs to know which dog was liked so that it can update the likes count for that dog. &lt;/p&gt;

&lt;p&gt;With all the card elements in place I added a function to fetch the data that will be used in the card and displayed on the site. &lt;/p&gt;

&lt;p&gt;I wrote the renderOneDog function before the function that fetches the dog data because I use renderOneDog inside the function that fetches the data. I named the fetch function getAllDogs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getAllDogs(){
   fetch('https://dogs-njbi.onrender.com/dogs')
   .then (response =&amp;gt; response.json())
   .then (dogData =&amp;gt;
       {dogData.forEach(dog =&amp;gt; renderOneDog(dog));
   // Note: I will not touch on the mostLikedDog element in this blog post as this data doesn’t display in the gallery. 
   mostLikedDog = dogData.reduce((prev, current) =&amp;gt; (prev.likes &amp;gt; current.likes) ? prev : current);
   renderMostLikedDog();
})
// 
   .catch (error =&amp;gt; console.error("Error fetching dogs", error));
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;getAllDogs fetches data from the json-server. The data is fetched using a GET request to &lt;a href="https://dogs-njbi.onrender.com/dogs"&gt;https://dogs-njbi.onrender.com/dogs&lt;/a&gt;. The function first converts the response to JSON format, which allows the data to be easily parsed and manipulated as a JavaScript object. This is necessary as it allows me to iterate over the data. &lt;/p&gt;

&lt;p&gt;The function then iterates over each dog in the data, using a forEach iteration, calling the renderOneDog function to render each dog card. Through this, the function allows me to dynamically display the dog cards based on the data received from the server.&lt;/p&gt;

&lt;p&gt;I added the .catch method for my own debugging purposes. I use it to handle errors that might occur when the data is being fetched. If an error is encountered during the fetch operation the .catch method is called and used to log the error message to the console along with the error object that was caught. &lt;/p&gt;

&lt;p&gt;Next, lets handle that the like functionality &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYzQ0d3plc2E0N3lpdzV4ZWUwYnlubnRheXRhdHFnN2h3bGU1dWRhZCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ZbOHizQnaxgL5gKfTS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYzQ0d3plc2E0N3lpdzV4ZWUwYnlubnRheXRhdHFnN2h3bGU1dWRhZCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ZbOHizQnaxgL5gKfTS/giphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn’t make sense to display the number of likes a dog has received if a user can’t also like a dog. I wanted to add a like button to encourage user interactivity, engagement and investment. &lt;/p&gt;

&lt;p&gt;You will have noticed this line of code in my renderOneDog function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;card.querySelector('.like-btn').addEventListener('click', handleLike);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I added an event listener to the like button. When clicked the handleLike function is called, which is the function where I handle the logic of what will happen when a user clicks on the button. In this context, the handleLike function is a callback function, as it is passed as an argument to another function (in this case, addEventListener) and is executed later, in response to a click on the like button. &lt;/p&gt;

&lt;p&gt;For anything to happen I needed to write the handleLike function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function handleLike(event) {
   const dogId = event.target.dataset.id;
   const card = event.target.parentElement;
   const likesElement = card.querySelector('.like');
   let likesCount = parseInt(likesElement.textContent.match(/\d+/)[0]);


   likesCount++;


fetch(`https://dogs-njbi.onrender.com/dogs/${dogId}`, {
       method: 'PATCH',
       headers: {
           'Content-Type':'application/json',
           'Accept': 'application/json'
       },
       body: JSON.stringify({
           likes: likesCount
       })
       })
       .then(response =&amp;gt; response.json())
       .then(updatedDog =&amp;gt; {
           likesElement.textContent = `${updatedDog.likes} likes`;
       })
       .catch(error =&amp;gt; console.error("Error updating dog likes", error));
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The handleLike function is responsible for updating the number of likes a dog has when the user clicks the like button on a card.&lt;/p&gt;

&lt;p&gt;First, the function identifies the elements associated with the dog: dogId, card, and likesElement. It then extracts the current number of likes from the likesElement, converts it to an integer using parseInt, and stores it in the likesCount variable.&lt;/p&gt;

&lt;p&gt;Next, it increments the likesCount variable to simulate the user liking the dog.&lt;/p&gt;

&lt;p&gt;The function then makes a PATCH request to the API endpoint for the specific dog (&lt;a href="https://dogs-njbi.onrender.com/dogs/$%7BdogId%7D"&gt;https://dogs-njbi.onrender.com/dogs/${dogId}&lt;/a&gt;). After the request, the response is converted to JSON format. The .then(updatedDog =&amp;gt; { ... }) block updates the text content of likesElement to display the updated number of likes.&lt;/p&gt;

&lt;p&gt;Finally, the initialise function is called to start the processes of fetching and rendering dogs on the app when the site loads, as well as the like function which updates the likes in the DOM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function initialise(){
   getAllDogs();
}
initialise();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it, a quick overview of the Javascript code. Javascript out. &lt;/p&gt;

&lt;p&gt;All this code makes up the foundation and key functionality of the contestants gallery, but without CSS the gallery wouldn’t have flesh, emotion, or expression. So let’s add some of that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExd3V2ajA2MWVyc3p6Y2FvMnBkYWxwamNwZGZhZzYxMmg3eWQ3djkzbCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/XT9HMdwmpHqqOu1f1a/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExd3V2ajA2MWVyc3p6Y2FvMnBkYWxwamNwZGZhZzYxMmg3eWQ3djkzbCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/XT9HMdwmpHqqOu1f1a/giphy.gif" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Design Design
&lt;/h2&gt;

&lt;p&gt;My vision for the gallery was to present the dog data in a simple, professional, and visually appealing way, while also engaging the user.&lt;/p&gt;

&lt;p&gt;I knew I wanted the gallery to be a scrolling gallery, that I wanted something to happen when the user hovered over the gallery card and that I wanted the like button to sit outside of the card so that it was always visible, encouraging user engagement. &lt;/p&gt;

&lt;p&gt;After researching and experimenting with different designs, I settled on a flip gallery layout. This design allowed me to keep the initial gallery view visually appealing with just an image of the dog and a like button, while the back of the card could contain additional information about the dog.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExdDJxdndpbmQ3MGkybWx2Y2UxcXRxZjdncmVsZWp5ZTk5c2hiOGp1ZCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/FN3nE4gP0gM1lPOIY8/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExdDJxdndpbmQ3MGkybWx2Y2UxcXRxZjdncmVsZWp5ZTk5c2hiOGp1ZCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/FN3nE4gP0gM1lPOIY8/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what my CSS code for the gallery looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card-gallery {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    min-height: 400px;
    gap: 20px;
    scroll-snap-type: x mandatory;
}

.card-gallery::-webkit-scrollbar {
    display: none; /* Hiding scrollbar for Chrome, Safari */
}

.card:first-child {
    padding-left: 20px;
}

.card {
    text-align: center;
    flex: 0 0 auto;
    scroll-snap-align: start;
    width: 300px;
    height: 300px;
    transform-style: preserve-3d;
    -webkit-transform-style: preserve-3d;
    transform: translateZ(0);
    -webkit-transform: translateZ(0); /* Safari flip gallery fix*/
}

.card-inner {
    width: 100%;
    height: 100%;
    transition: transform 0.5s;
    transform-style: preserve-3d;
    -webkit-transform-style: preserve-3d; /* Safari flip gallery fix*/
}

.card:hover .card-inner {
    transform: rotateY(180deg);
    -webkit-transform: rotateY(180deg); /* Safari flip gallery fix*/
}

.card-front,
.card-back {
    width: 100%;
    height: 100%;
    position: absolute;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden; /* Safari flip gallery fix*/
}

.card-front {
    display: flex;
    justify-content: center;
    align-items: center;
}

.card-back {
    background-color: #4a6163;
    color: #f9faf4;
    text-align: center;
    transform: rotateY(180deg);
    -webkit-transform: rotateY(180deg); /* Safari flip gallery fix*/
    border-radius: 10px;
}


.card-back p {
    font-family: "Roboto", sans-serif;
    font-weight: 300;
    font-style: normal;
    font-size: 15px;
    padding: 10px;
    letter-spacing: 0.5px;
}

.card-back .like {
    font-style: italic;
}

.dog-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 10px;
}

.like {
    text-align: center;
    margin-top: 10px;
}

.like-btn {
    display: block;
    margin: 10px auto;
    background-color: #4a6163; 
    color: #f9faf4;;
    border: none;
    width: 100px;
    height: 40px;
    font-family: "Roboto", sans-serif;
    font-weight: 300;
    font-style: normal;
    font-size: 15px;
    letter-spacing: 0.5px;
    cursor: pointer;
    border-radius: 10px;
}

.like-btn:hover {
    background-color: #f17a7e;
    color: #f9faf4;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phew. That’s a lot of code! &lt;/p&gt;

&lt;p&gt;The key things to point out in the CSS are the elements that make the gallery cards flip. &lt;/p&gt;

&lt;p&gt;In the CSS for the gallery cards, .card-gallery styles the gallery container using flexbox, allowing for horizontal scrolling and preventing card wrapping. .card styles each card, centering content, setting dimensions, and enforcing no grow or shrink. .card-inner styles the inner content for flip animation, while .card:hover .card-inner handles the flip effect on hover. .card-front and .card-back style the front and back faces of each card, with .card-back initially rotated to hide it.&lt;/p&gt;

&lt;p&gt;This does not cover all the styles in the CSS code above, but highlights those relevant to the flip effect.The flip effect adds an element of fun and interactivity to the user experience, especially when a user hovers over the dog image. This interactivity extends to the like button, which updates the number of likes on the back of the card after a click, enhancing user engagement.&lt;/p&gt;

&lt;p&gt;The end result is not exactly, to the detail, what I had envisioned when I started my journey, but as a result of only 12 weeks of coding experience I am satisfied with how it ended up looking and working. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYnN5NXZrazlkY3ozcXFtZHoyc29pM21maDcyNWd2cmczbGo2ajZ5YyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3ohhwGwvnyjI6l9bFu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYnN5NXZrazlkY3ozcXFtZHoyc29pM21maDcyNWd2cmczbGo2ajZ5YyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3ohhwGwvnyjI6l9bFu/giphy.gif" width="500" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading. &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
